Java
Lock比传统线程模型中的synchronized方式更加面向对象,也提供了更多可选择的锁机制。与生活中的锁类似,锁本身也是一个对象。两个线程执行的代码片段要实现同步互斥的效果,它们必须使用同一个Lock对象。
Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait
做的那样。
Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得 Condition
实例,请使用其newCondition()
方法。一个ReentrantLock可以new 出多个条件Condition:
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
下面我们来看
ReentrantLock相关api
void lock();
获取锁。
如果锁不可用,出于线程调度目的,将禁用当前线程,并且在获得锁之前,该线程将一直处于休眠状态。
void lockInterruptibly() throws InterruptedException;
如果当前线程未被中断,则获取锁。如果锁可用,则获取锁,并立即返回。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下两种情况之一以前,该线程将一直处于休眠状态:
锁由当前线程获得;或其他某个线程中断当前线程,并且支持对锁获取的中断。如果当前线程;在进入此方法时已经设置了该线程的中断状态;或者
在获取锁时被中断,并且支持对锁获取的中断,则将抛出 InterruptedException,并清除当前线程的已中断状态。
Condition newCondition();
返回绑定到此 Lock 实例的新 Condition 实例。下一小节中会重点谈Condition,此处不做过多的介绍。
boolean tryLock();
仅在调用时锁为空闲状态才获取该锁。
如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false。
通常对于那些不是必须获取锁的操作可能有用。
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
如果锁可用,则此方法将立即返回值 true。如果锁不可用,出于线程调度目的,将禁用当前线程,并且在发生以下三种情况之一前,该线程将一直处于休眠状态:
void unlock() <span style="font-family: simsun;">释放锁;</span>
下面我们也来看一下Condition api
</pre></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"><span style="font-size:18px;">signalAll:唤醒在此监视器上面的所有线程,</span></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"><span style="font-size:18px;">signal:唤醒在此监视器上面的某一条线程,一般是随机的一条线程,</span></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"><span style="font-size:18px;">await;等待和Object 的wait一样,</span></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"><span style="font-size:18px;">await(time, unit);在一定的时间内等待和Object wait(time,unit)用法一样。</span></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"></p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;">下面我们来看一下使用实例:</p><p style="margin-top: 0px; margin-bottom: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; list-style: none; word-wrap: normal; word-break: normal; line-height: 21px; font-family: simsun; text-indent: 28px;"><pre name="code" class="java">package javaThread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionCommunication {
/**
* @param args
*/
public static void main(String[] args) {
final Business business = new Business();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1; i++) {
business.sub2(i);
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1; i++) {
business.sub3(i);
}
}
}).start();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1; i++) {
business.main(i);
}
}
}).start();
}
static class Business {
private int shouldSub = 1;
private Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
public void sub2(int i) {
try {
lock.lock();
while (shouldSub != 2) {
try {
condition2.await();
} catch (Exception e) {
e.printStackTrace();
}
}
for (int j = 1; j <= 5; j++) {
System.out
.println("sub2 thread sequence is @@@@@@@@@@@@" + j + " loop of " + i);
}
shouldSub = 3;
condition3.signal();
} finally {
lock.unlock();
}
}
public void sub3(int i) {
try {
lock.lock();
while (shouldSub != 3) {
try {
condition3.await();
} catch (Exception e) {
e.printStackTrace();
}
}
for (int j = 1; j <= 5; j++) {
System.out.println("sub3 thread sequence is #############" + j + " loop of "
+ i);
}
shouldSub = 1;
condition1.signal();
} finally {
lock.unlock();
}
}
public void main(int i) {
try {
lock.lock();
System.out.println("main thread sequence is $$$$$$$$$$$$ ^^"
+ Thread.currentThread().getName());
while (shouldSub != 1) {
try {
condition1.await();
} catch (Exception e) {
e.printStackTrace();
}
}
for (int j = 1; j <= 5; j++) {
System.out
.println("main thread sequence is $$$$$$$$$$$$" + j + " loop of " + i);
}
shouldSub = 2;
condition2.signal();
condition2.await(time, unit);
} finally {
lock.unlock();
}
}
}
}