在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
1.对象的锁
所有对象都自动含有单一的锁。
JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。
只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。
每当任务离开一个synchronized方法,计数递减,当计数为0的时候,锁被完全释放,此时别的任务就可以使用此资源。
2.synchronized同步块
synchronized有两种格式:

格式1:
synchronized(任何对象){
  //访问共享变量的临界区(程序段),又称同步代码块
}
格式2:同步化方法。在方法的前面加上synchronized,如:
public synchronized void add() {
//临界区
}
共享变量所关联的对象锁是如何选择的?即
synchronized (任何对象) {
//临界区
}
  1.synchronized锁定的是一个具体对象,通常是共享变量的对象。用synchronized括起来的程序段是访问该共享变量的临界区,即synchronized代码块。由于所有锁定同一个对象的线程之间,在synchronized代码块上是互斥的,也就是说,这些线程的synchronized代码块之间是串行执行的,不再是互相交替穿插并发执行,因而保证了synchronized 代码块操作的原子性。但synchronized代码块与所有线程的非synchronized 代码块之间以及非synchronized代码块与非synchronized代码块之间都是互相交替穿插并发执行的,故synchronized代码块操作的原子性是逻辑上的,而不是物理上的不可打断。

 2.每一个Java对象都有且只有一个对象锁。任何时刻,一个对象锁只能被一个线程所拥有。若两个或多个线程锁定的不是同一个对象,则它们的synchronized代码块可以互相交替穿插并发执行。
 
3.所有的非synchronized代码块或方法,都可自由调用。如线程A获得了对象锁,调用需要该对象锁的synchronized代码块,其他线程仍然可以自由调用所有非synchronized方法和代码
 
4.若线程A获得了对象O的对象锁,调用对象O的synchronized代码块或方法,则线程A仍然可以调用其他任何需要对象O的锁的synchronized代码块或方法,这是因为线程A已经获得了对象O的对象锁了。线程A同时可以调用需要另一个对象K的锁的synchronized代码块或方法,这意味着线程A同时拥有对象O和对象K的对象锁。
 
5.只有当一个线程执行完它所调用的synchronized代码块或方法时,无论是正常执行完,还是异常抛出,该线程才会释放所获取的对象锁。synchronized并不必然地保护数据。程序员应该仔细分析,识别出程序中所有的临界区,并对这些临界区施加synchronized机制。若有一处或多处遗漏,则共享变量中数据就会产生错误
 
6.临界区中的共享变量应定义为private型。否则,其他类的方法可能直接访问和操作该共享变量,这样synchronized的保护就失去了意义。所以只能通过临界区访问共享变量。故锁定的对象通常是this,即通常格式都是:synchronized(this){…}
 
7.一定要保证,所有对共享变量的访问与操作均在synchronized代码块中进行。
 
8.通常共享变量都是实例变量。若临界区中的共享变量是一个类变量,则问题复杂化了,因为类方法与实例方法均可访问类变量。而synchronized锁定的必须是对象,不能是类。建议是若临界区中的共享变量是一个类变量,则应该用类方法来访问操作该类变量。这个类方法成为一个临界区,必须将该类方法定义为synchronized方法。所有要访问该共享类变量的实例方法,都应该调用定义为synchronized的类方法进行。若实例方法一定要想在自己的代码内部,不通过synchronized的类方法访问共享类变量,则可通过synchronized(类名.class){…来访问类锁。Java中,每一个类都有一个类对象,这个类对象实际上是java.lang.Class的一个实例对象,所谓类锁就是这个类对象的一把锁。注意类锁与这个类的实例对象的对象锁虽然都是对象锁,却是不同的两把锁。所有像synchronized(类名.class()){=同步代码块} 这样锁定类对象(注意:不是锁定类的某一个实例对象),其中的synchronized代码块,都是串行执行的,访问或使用类锁要仔细考虑和权衡
 
9.当一个线程进入死亡状态,线程拥有的所有的对象锁都被释放。
3.Lock对象锁
 

Java SE5引入了java.util.concurrent.lock类库,这是解决互斥问题的第二种机制。用ReentrantLock类创建一个Lock对象,来保护临界区。用ReentrantLock保护代码块的基本结构如下。
private Lock locker =new ReentrantLock();
locker.lock(); // 加锁
try{
}finally{
  locker.unlock(); // 解锁
  }
lock()与unlock()必须配套使用。必须确保lock()对应的unlock()一定会得到执行。因此,必须把unlock()放到finally块中,确保无论是正常执行,还是异常抛出,unlock()一定会得到执行。
 
 
synchronized和lock的区别:
 
Lock 的锁定是通过代码实现的,而 synchronized 是在 JVM 层面上实现的
synchronized 在锁定时如果方法块抛出异常,JVM 会自动将锁释放掉,不会因为出了异常没有释放锁造成线程死锁。但是 Lock 的话就享受不到 JVM 带来自动的功能,出现异常时必须在 finally 将锁释放掉,否则将会引起死锁。
 
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。

ReentrantLock: 
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

Atomic: 
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。 

 
 

JAVA--对象锁的更多相关文章

  1. [转]Java 对象锁-synchronized()与线程的状态与生命周期

      线程的状态与生命周期 Java 对象锁-synchronized() ? 1 2 3 4 synchronized(someObject){   //对象锁 } 对象锁的使用说明: 1.对象锁的返 ...

  2. java 对象锁和类锁的区别(转)

    java 对象锁和类锁的区别   转自; ) ); ; ) ); 上述的代码,第一个方法时用了同步代码块的方式进行同步,传入的对象实例是this,表明是当前对象,当然,如果需要同步其他对象实例,也不可 ...

  3. Java对象锁和类锁全面解析(多线程synchronized关键字)

    最近工作有用到一些多线程的东西,之前吧,有用到synchronized同步块,不过是别人怎么用就跟着用,并没有搞清楚锁的概念.最近也是遇到一些问题,不搞清楚锁的概念,很容易碰壁,甚至有些时候自己连用没 ...

  4. java 对象锁学习

    机制 锁机制是用来解决多线程共享资源时产生的冲突问题的.java 为每一个对象关联一个对象锁,通常把锁分为对象锁和类锁,他们的本质都是对象锁,只不过对象锁关联的是类的 Object 对象 (java. ...

  5. paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象)

    paip.提升性能----java 无锁结构(CAS, Atomic, Threadlocal, volatile, 函数式编码, 不变对象) 1     锁的缺点 2     CAS(Compare ...

  6. java synchronized类锁,对象锁详解(转载)

    觉得还不错 留个记录,转载自http://zhh9106.iteye.com/blog/2151791 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看 ...

  7. java 哪些情况下会使对象锁释放

    Java_多线程_锁释放 问:Java多线程运行环境中,在哪些情况下会使对象锁释放?答:由于等待一个锁的线程只有在获得这把锁之后,才能恢复运行,所以让持有锁的线程在不再需要锁的时候及时释放锁是很重要的 ...

  8. Java:使用synchronized和Lock对象获取对象锁

    在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制. 1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被解锁,其计数变为0.在任务(线程)第一次给对象加锁 ...

  9. Java虚拟机14:Java对象大小、对象内存布局及锁状态变化

    一个对象占多少字节? 关于对象的大小,对于C/C++来说,都是有sizeof函数可以直接获取的,但是Java似乎没有这样的方法.不过还好,在JDK1.5之后引入了Instrumentation类,这个 ...

  10. Java锁Synchronized,对象锁和类锁举例

    Java的锁分为对象锁和类锁. 1. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内针对该对象的操作只能有一个线程得到执行.另一个线程必须 ...

随机推荐

  1. IOS代理

    之前看过一些关于代理的资料,始终感觉还是很模糊,最近抽出一段空闲的时间,将这块内容整理下: 什么是代理,顾名思义就是帮别人做些事情,比如买房子,当我们买房子时,我们一般会找房屋中介,因为他们就是干这件 ...

  2. android 开源框架推荐

    同事整理的 android 开源框架,个个都堪称经典.32 个赞! 1.volley 项目地址 https://github.com/smanikandan14/Volley-demo (1)  JS ...

  3. 初用jquery

    ---恢复内容开始--- 这两天在顶顶大人的指导下,利用jquery框架做了一个动态切换的小页面.最终效果图: 这么萌萌哒的图片让我觉得一直在测试也没那么累.实现功能如下: 1.打开页面时,自动切换, ...

  4. yii2源码学习笔记(十一)

    Controller控制器类,是所有控制器的基类,用于调用模型和布局. <?php /** * @link http://www.yiiframework.com/ * @copyright C ...

  5. php 定时执行任务

    之于是否控制,可以做到的,应借用第三个条件: config.php <?phpreturn 1;?> cron.phpignore_user_abort();//关掉浏览器,PHP脚本也可 ...

  6. cocos2d-x Tests讲解 Particle System(粒子系统)

    转载请注明出处: http://www.cnblogs.com/shangdahao/archive/2012/04/14/2447571.html 一.粒子系统简介: 粒子系统最早出现在80年代,主 ...

  7. ACdream训练赛系列のJava专场

    /* * this code is made by mhy12345 * Problem: 1669 * Verdict: Accepted * Submission Date: 2015-04-21 ...

  8. jquery mobile backbone

    http://www.appliness.com/getting-started-with-html-mobile-application-development-using-jquery-mobil ...

  9. XXX is not in the sudoers file.This incident will be reported

    在fefora 10安装xz解压软件时,sudo make install 时,报错: 原因未知,在网上搜索为:权限问题,解决办法如下(来自百度): 解决方法如下: >.进入超级用户模式.也就是 ...

  10. 两种方法,获取磁盘剩余空间--PYTHON

    import ctypes import os import platform import sys def get_free_space_mb(folder): """ ...