顶层接口:
- lock() // 如果锁可用就获得锁,如果锁不可用就阻塞直到锁释放
- lockInterruptibly() // 和 lock()方法相似, 但阻塞的线程可中断,抛出 java.lang.InterruptedException异常
- tryLock() // 非阻塞获取锁;尝试获取锁,如果成功返回true
- newCondition()
- unlock()
Condition:
为线程提供了等待、通知机制(wait、signal)
- 等待(Await):
- 当一个线程持有相关的Lock但希望暂时释放锁,并等待某个条件变为真时,它可以调用Condition的await()方法。这类似于Object的wait()方法。调用await()会使当前线程进入等待状态直到它被通知或被中断。
- 通知(Signal):
- 另一个线程可以通过调用Condition的signal()或signalAll()方法来唤醒一个或所有等待的线程。这类似于Object的notify()或notifyAll()方法。调用signal()会唤醒一个等待在Condition上的线程,而signalAll()会唤醒所有等待的线程。
await():
将当前线程加入condition的等待队列
释放当前condition对应的锁
当前线程被挂起(阻塞)(使用LockSupport.park)
signal:
使用LockSupport.unpark,进行解锁
常见用法
1、生产者、消费者
一个锁,分两个condition
- notFull
- notEmpty
生产者等notFull
消费者等notEmpty
Q:为什么不用两个锁
A:
1、因为消费队列是同一个,用一个锁可以更好的保证共享数据的一致性
2、通知更加精确,不会通知到无关的线程
3、简化了代码逻辑
4、性能优化
5、避免信号丢失
常见实现
1、ReentrantLock
2、ReentrantReadWriteLock
3、StampedLock
参考: