性质:可重入,不可中断
两种用法:对象锁(方法锁,同步代码块锁),类锁(静态方法,class对象)
多线程访问同步方法的7种情况
加解锁原理(计数器加减),可重入原理,可见性原理(写回主内存再通信)
书籍:Java并发编程实战
对象锁
同步代码块
1 | synchronized (this){ |
1 | Object lock1 = new Object(); |
方法锁
1 | public synchronized void addition(){ |
类锁
静态方法
1 | public synchronized static void addition(){ |
class对象
1 | synchronized (*.class){ |
7种常见情况
- 两个线程同时访问一个对象的同步方法 – 串行
- 两个线程访问两个对象的同步方法 – 并行
- 两个线程访问synchronized得静态方法 – 串行
- 同时访问同步和非同步方法 – (一个线程访问同步方法,一个访问非同步,不影响)并行
- 访问同一个对象的不同的普通同步方法(非static方法) – (同一个实例默认使用this)串行
- 同时访问静态synchronized和非静态synchronized方法 – 并行
- 方法抛异常后会释放锁 – Lock类型的锁不会释放
性质
可重入
同一线程的外层函数获得锁之后,内层函数可直接再次获取该锁(同一把锁)
内层函数可以是1.同一个方法2.不同方法3.不同类(子父类)
好处:避免死锁,提升封装性
粒度:线程而非调用(pthread的粒度是调用)
不可中断
Lock接口
1 | Lock lock = new ReentrantLock(); |
反编译
1 | javac test.java //编译 |
缺陷
- 效率低:不可中断,不能设置超时,锁释放情况少
- 不够灵活:加锁释放时机单一,每个锁仅有单一条件(对比之下,读写锁更加灵活)
- 无法知道是否成功获取到锁
注意点
锁对象不能为空
作用域不宜过大
避免死锁
Lock与synchronized尽量避免使用,可以使用java.util.concurrent
包下的各种工具类
synchronized代码更简洁
同步访问的各种情况
锁的优化
锁的升级降级,偏斜锁,轻量级锁,重量级锁