多线程---再次认识volatile,Synchronize,lock
Posted wangdan1030
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程---再次认识volatile,Synchronize,lock相关的知识,希望对你有一定的参考价值。
在多线程中我们常用的保证共享变量的方法有很多,现在我们介绍其中的一种,volatile,也是效率最高的一种。 一 、volatile的意义: 为了确保共享变量能被正确和一致的更新,字段被声明称volatile,java线程内存模型确保所有线程看到这个变量的值是一致的。volatile变量修饰符如果使用恰当的话,它比synchronize的使用和执行成本更低,因此它不会引起线程上下文的切换和调度。二 、如何保证所有线程看到的这个变量的值是一致的? 源码中有这样一句, instance = new Singleton();说明这是一个单例,任何线程请求的都是这一个对象。生成汇编代码:
在汇编代码中会出现 一个lock前缀,有这个前缀会发生两件事: 1.当前处理器的缓存行的数据都会写回到系统内存。 2.这个写回内存的操作会引起其他CPU缓存的该内存地址的数据无效。 为什么好多的都设64个字节,或是hash的一些默认空间设置成16个,原因与处理器结构有关,一般处理器缓存的额告诉缓存行时64个字节宽,换句话说他可以放16个对象,所以追加字节能优化性能。一些我们常见的java集合都是默认的设置空间为16。 三 、 与Synchronize、lock的区别
1.synchronize是一种机制,可加在方法上,也可以加载语句块上;lock是一个对象,多线程需要一个ReentrantLock才能实现锁机制。 2.synchronize是托管给JVM管理的,lock是java代码写的控制锁的实现。 3.synchronized采用的是悲观锁机制,线程获得的是独占锁,只能依靠阻塞来等待线程释放锁。而且CPU转换线程时上下文切换回引起新城竞争锁,使得效率降低。lock 采用的是乐观锁机制,乐观锁其实就是不加锁,一直去操作,失败就重新操作,直到成功为止,效率高很多。 4.当竞争不激烈的时候synchronize的性能好一点儿,但是当竞争激烈的时候lock的性能要很多。 四 、在JVM中锁是如何工作的:
1.java对象头:hashcode,锁,分代年龄。在运行期间MarkWord 里存储的数据会随着锁标志位的变化而变化,可能变化为下面的数据:
2锁的状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态。 3 锁状态比较:
锁 | 优点 | 缺点 | 适用场景 |
偏向锁 | 加锁和解锁不需要额外的消耗,和执行非同步方法比仅存在纳秒级的差距 | 如果宣布从个别个驻华吧创业板在锁竞争,会带来额外的锁撤销的消耗 | 适用于只有一个线程访问同步块场景 |
轻量级锁 | 竞争的线程不会阻塞,提高了程序的效应速度 | 如果始终得不到锁竞争的线程使用自旋会消耗CPU | 追求相应时间,同步块儿执行速度非常快 |
重量级锁 | 线程竞争不适用自旋,不会消耗CPU,但是枷锁解锁过程会消耗CPU, | 线程阻塞,相应时间缓慢 | 追求吞吐量,同步块执行速度较长 |
以上是关于多线程---再次认识volatile,Synchronize,lock的主要内容,如果未能解决你的问题,请参考以下文章
Java多线程基础-第一节4:synchronized关键字(监视器锁monitor lock)和volatile关键字