一、线程间通信的方式
首先,介绍以下几种线程间的通信方式:
协作方式 | 死锁方式1(通过主动加把锁) | 死锁方式1(先唤醒再挂起) | 备注 |
---|---|---|---|
suspend/resume | 死锁 | 死锁 | 弃用 |
wait/notify | 不死锁 | 死锁 | 只能在synchronized关键字中用,基于对象监视器 |
park/unPark | 死锁 | 不死锁 | 用LockSupport,令牌机制 |
condition的await/signal | 不死锁 | 死锁 | 只能在ReentrantLock中用 |
二、Synchronized与Lock的对比
(1)Synchronized优点:使用简单;由JVM提供,包括了多种优化方式(锁升级,具体可看我Synchronized原理的博客);锁的释放不用人工干预,由JVM释放,降低了死锁的可能性。
(2)Synchronized缺点:无法使用锁的高级功能,如读写锁等,使用不灵活。
(3)Lock优点:所有Synchronized的缺点,Lock都可以解决。
(4)Lock缺点:需要手动释放锁调用unLock()方法,使用不当可能造成死锁。
三、Lock接口读写锁原理介绍
读写锁维护了一对关联锁,读锁只用于读操作,可同时被多个线程持有;写锁只用于写操作,同时只能被一个线程持有;并且在同一时间读锁和写锁也不能被同时持有,它适合读多写少的情况。读写锁的API如下:
public class ReadWriteLockTest {
volatile long i = 0;
//读写锁
ReadWriteLock rwLock = new ReentrantReadWriteLock();
//读方法
public void read() {
rwLock.readLock().