在并发环境下,解决共享资源冲突问题时,可以考虑使用锁机制。
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. ubuntu desktop 开机 连接网络

    参考   http://linux.net527.cn/Ubuntu/Ubuntuanzhuangyuyingyong/2490.html

  2. 每天一条linux命令——shutdown

    shutdown命令用来系统关机命令.shutdown指令可以关闭所有程序,并依用户的需要,进行重新开机或关机的动作. 语法: shutdown(选项)(参数) 选项: -c:当执行“shutdown ...

  3. 负载均衡-多台机子session不起效:把php.ini中file改为memcache存储

    一 开启memcache服务 二 修改php.ini中session配置 php/lib/php.ini session.save_handler = memcache session.save_pa ...

  4. PHPCMS二次开发教程

    PHPCMS V9 结构设计 根目录|–api  结构文件目录|–caches 缓存文件目录   |– configs 系统配置文件目录   |– caches_* 系统缓存目录|–phpcms  p ...

  5. c#指针用法示例。

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  6. web系列教程之php 与mysql 动态网站 。检索 与更新。

    接着上次WEb 系列开发之php 与mysql动态网站入门. 个人觉得,学习技术就像一棵大树,主干很重要,枝叶其次.对于学习技术,我们应该分清主次关系.怎么学?为什么要学?有一个较好的分寸. 有时候觉 ...

  7. Entity Framework Code First 数据迁移

    需要在[工具 --> NuGet 程序包管理器 --> 程序包管理器控制台]中输入三个命令: Enable-Migrations (初次迁移时使用) Add-Migration [为本次迁 ...

  8. 在 IIS MIME 类型中添加 md 扩展名

    最近在了解 Knowledge Base (知识库)的内容,对两个平台比较感兴趣,一个是 Raneto,一个是 MDwiki,两者都是使用md文件作为内容存储. 需要注意的是,使用IIS部署网站后,需 ...

  9. Js 中json简单处理

    Json2.js下载地址 json常用处理 Json字符串 var str = '{"code":10,"msg":"codemsg",&q ...

  10. vc6静态库的生成和调用

    转自vc6静态库的生成和调用 1.静态库的生成: 在vc6.0++中Ctrl+N选择Projects下的Win32 Static Library,Project name:SumLib,点击OK,下一 ...