多线程经常使用的3个关键字:synchronized、ReentrantLock、volatile
来源:互联网 发布:powermill10软件下载 编辑:程序博客网 时间:2024/05/29 19:16
3个关键字synchronized、ReentrantLock、volatile。
一、synchronized
互斥锁,即操作互斥,并发线程过来,串行获得锁,串行执行代码。就像一个房间一把钥匙,一个人进去后,下一个人得等第一个人出来得到钥匙才能进入。如果代码写的不好(A),可能出现死锁!(A得到锁,B等待A释放锁,A不释放,B死锁)
示例代码:
//修饰静态方法:类级别互斥(只要是房子此方法就互斥) public synchronized static void foo1(){ //do } //修饰普通方法:对象级别互斥(只有同一间房子此方法互斥) public synchronized void foo2(){ //do } //修饰代码块 public void foo3(){ //类级别互斥 synchronized(DennyTest.class) { //do } } //修饰代码块 public void foo4(){ //对象级别互斥 synchronized(this) { //do } }
需要注意的是,经常使用的是对象级别的互斥,那么特别需要注意是同一个对象的锁。新手经常犯错,都不是同一个对象,当然锁不住。
二、ReentrantLock
可重入锁,和同步锁功能类似,不过需要显示的创建、销毁。特点:
1.ReentrantLock有tryLock方法,如果锁被其他线程持有,返回false,可避免形成死锁。
2.创建时可自定义是否可抢占。
3.ReentrantReadWriteLock,用于读多写少,且读不需要互斥的场景,大大提高性能。
示例代码:
1、尝试获取一次 ReentrantLock lock = new ReentrantLock(); if (lock.tryLock()) { //得到执行,得不到不执行,就一次。 try { //操作 } finally { lock.unlock(); } }2、同步执行,类似synchronized(也是使用最多的) ReentrantLock lock = new ReentrantLock(); //参数默认false,不公平锁:可抢占 ReentrantLock lock = new ReentrantLock(true); //公平锁:严格按照请求锁的排队顺序获取锁 lock.lock(); //如果被其它资源锁定,会在此等待锁释放,阻塞 try { //操作 } finally { lock.unlock(); } 3、尝试等待固定时间再次获取 ReentrantLock lock = new ReentrantLock(true); //公平锁 try { if (lock.tryLock(5, TimeUnit.SECONDS)) { //如果已经被lock,尝试等待5s,看是否可以获得锁,如果5s后仍然无法获得锁则返回false try { //操作 } finally { lock.unlock(); } } } catch (InterruptedException e) { e.printStackTrace(); //当前线程被中断时(interrupt),会抛InterruptedException }4、可中断锁的同步执行 ReentrantLock lock = new ReentrantLock(true); //公平锁 lock.lockInterruptibly(); try { //操作 } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); }
三、volatile
volatile,翻译过来是易变的。只保证同一变量在多线程中的可见性。
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
注意:虽然保证变量是主存数据,但是操作不是原子的,多线程读取到同一个值(是主存的值),同时进行判断或者操作,导致出错。
总结:
可见,synchronized和ReentrantLock是一个级别的,但是volatile只是一个轻量级的关键字。可用场景:
1.状态标记
1 volatile boolean inited = false; 2 //线程1: 3 context = loadContext(); 4 inited = true; 5 6 //线程2: 7 while(!inited ){ 8 sleep() 9 }10 doSomethingwithconfig(context);
2.double check :使用 volatile 关键字来保证多线程下的单例
public class Singleton { private volatile Singleton instance = null; public Singleton getInstance() { if (instance == null) { synchronized(this) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
参考资料:
《深入理解Java虚拟机》
《effective java》
http://www.cnblogs.com/dolphin0520/p/3920373.html
- 多线程经常使用的3个关键字:synchronized、ReentrantLock、volatile
- java并发编程synchronized、volatile关键字及ReentrantLock类总结
- volatile,synchronized,ReentrantLock
- volatile、ThreadLocal、synchronized等3个关键字区别
- volatile、ThreadLocal、synchronized等3个关键字区别
- java多线程之synchronized和volatile关键字
- JAVA多线程系列--关键字(volatile,synchronized)
- Java的3个问题:synchronized方法、volatile关键字、及内部类
- volatile、synchronized、AtomicInteger多线程累加1000个计数的区别
- Java多线程同步 synchronized 关键字的使用
- [转载]关于native,transient,volatile,synchronized四个关键字的使用
- 关于native,transient,volatile,synchronized四个关键字的使用
- 关于native,transient,volatile,synchronized四个关键字的使用
- java多线程 synchronized volatile Atomic LOCK的使用
- java中volatile、synchronized 关键字的含义
- volatile和synchronized关键字的区别
- java中volatile、synchronized关键字的含义
- Java单例模式及创建单例模式的多线程问题 volatile synchronized 关键字
- 常用线程池和调度类
- hibernate与mybatis对比
- Server IPC version 9 cannot communicate with client version 4
- mysql可扩展性
- 端口分类调研
- 多线程经常使用的3个关键字:synchronized、ReentrantLock、volatile
- 31 《象与骑象人:幸福的假设》 -豆瓣评分8.4
- MC9S12XEP100 SCI(UART)驱动程序2
- Eclipse的操作技巧
- vs2015单元测试总结——3种方法可用
- UVa 563
- SQL Server 2008如何开启数据库的远程连接
- 在《JavaScript高级程序设计》的一些笔记
- 字符串面试题