四、线程同步之Lock和Condition
Lock同步锁
Lock
在jdk1.5 提供了Lock以便执行同步操作,和synchronized不同的是Lock提供了显示的方法获取锁和释放锁。Lock提供了以下几个方法,请求和释放锁:
- void lock()
获取锁,当前锁若是不可用的时候,此线程将休眠直到锁被获取到。 - void lockInterruptibly()
获取锁,当前锁若是不可用,此线程将休眠直到锁被获取。有两种情况线程不会休眠:
1、当前线程获取了锁
2、其他线程终止了当前线程,并且终止获取锁是被允许的。 - boolean tryLock()
获取锁,当前锁可用则返回'true',反之返回'false';使用方法如下:Lock lock = ...;if (lock.tryLock()) {try {// manipulate protected state} finally {lock.unlock();}} else {// perform alternative actions}
- boolean tryLock(long,TimeUnit)
获取锁,在规定的时间内,锁一直不可用返回'false',反之返回'true' - void unlock()
释放锁。使用事项:此方法和获取锁的几个方法一一对应,获取到了锁,必须最后调用此方法释放锁。 - Condition newCondition()
获取一个Condition对象,操作当前锁。
使用原则 获取锁==>run()==>释放锁。这一原则和synchronized是一样的,只是获取和释放时是显示调用的,也是因为lock和unlock的组合使用,多个同步方法能很方便的嵌套使用,执行完后会依次释放自己所持有的锁。如下:
Lock l = ...;l.lock();try{//do something} finally{l.unlock();}
通常锁提供了资源的独占访问,不过某些确实允许对资源的并发访问,如ReadWriteLock(读写锁),开发中常用的ReentantLock(可重入锁),比如下面使用方法:
class X {private final ReentrantLock lock = new ReentrantLock();// ...public void m() {lock.lock(); // block until condition holdstry {// ... method body} finally {lock.unlock()}}}
Condition
使用Lock替换了Synchronized实现同步操作时,Condition替换了Object 监视器方法的使用。
Conditions (也可以称为条件队列或者条件变量)为某些行为提供了用途,如一个线程需要等待,直到某些条件为ture,被其他线程唤醒。因为在不同线程里访问共享信息是必须受到保护,因此锁的状态根据某些条件决定的。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait 做的那样。
一个锁绑定了一个Condition对象。可以通过Lock的newCondition()方法获取。下面写了一个小例子:
class BoundedBuffer {final Lock lock = new ReentrantLock();final Condition notFull = lock.newCondition();final Condition notEmpty = lock.newCondition();final Object[] items = new Object[100];int putptr, takeptr, count;public void put(Object x) throws InterruptedException {lock.lock();try {while (count == items.length)notFull.await();items[putptr] = x;if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();} finally {lock.unlock();}}public Object take() throws InterruptedException {lock.lock();try {while (count == 0)notEmpty.await();Object x = items[takeptr];if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();return x;} finally {lock.unlock();}}}
方法描述:
| Modifier and Type | Method and Description |
|---|---|
void | await()使当前线程处于等待状态,直到收到信号或者被打断. |
boolean | await(long time, TimeUnit unit) |
long | awaitNanos(long nanosTimeout) |
void | awaitUninterruptibly() |
boolean | awaitUntil(Date deadline)在规定时间里使当前线程处于等待状态,直到在这段时间内收到信号或者被打断。. |
void | signal()唤醒一个正在等待的线程. |
void | signalAll() |
补充
ReentrantLock 锁具有重入性,也就是说线程可以对它已经加锁的ReentrantLock锁再次加锁,ReentrantLock对象会维持一个计数器来跟踪lock方法的嵌套调用,线程在每次调用lock()加锁后,必须显式调用unlock()来释放锁,所以一段被锁保护的代码可以调用另一个被相同锁保护的方法。

浙公网安备 33010602011771号