Java Lock与Condition
2019-02-20 本文已影响0人
qingshuiting
Java Lock与Condition
Lock接口提供的方法
void lock();
void lockInterruptibly() throws InterruptedException; // 获得锁,或者被interrupt;如果锁已经获得就无法interrupt
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;// 获得锁;或者等待一段时间获得锁;
//在等待的过程中可以被interrupt
Condition newCondition();// 详细的介绍在下一节中
void unlock(); // release the lock
既然在Lock中出现这么多的interrupt,那么就不得不说下Thread的状态,以及如何控制Thread的中断状态了。
Thread的状态与interrupt
Thread类中有三个关于interrupt的方法:
public void interrupt() // 主动中断线程,其实就是将中断标志位set为true
public static boolean interrupted()// 检测是否中断,但是调用会clear 中断标志位
public boolean isInterrupted()// 不会clear中断标志位
如何中断
条件:线程处于阻塞状态(调用sleep,join,wait,或者可中断的I/O上)。
操作:在阻塞状态的时候检测中断标志位,如果为true,那么就抛出InterruptedException,在异常抛出的时候会恢复中断标志位。
condition与Lock的配合使用
在没有Lock之前,线程通信的一些实现方式需要使用synchronized
和Object
的监控方法来进行实现。在后来Java提供了Lock以及condition。
获得condition的方法
在Lock接口中有一个方法为:但是这个方法并不是所有的实现Lock接口的实现类中支持
Condition newCondition();
支持newCondition
的Lock有:ReentrantLock
和ReentrantReadWriteLock.WriteLock
。
condition的使用 vs Object monitor的使用
condition支持的操作:
// wait
void await() throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
long awaitNanos(long nanosTimeout) throws InterruptedException;
void awaitUninterruptibly();
boolean awaitUntil(Date deadline) throws InterruptedException;
// signal
void signal();
void signalAll();
condition使用的模板:
// wait 模板,signal 模板
lock.lock();
try{
// wait 条件:一般都是使用while
while(meet the condition){
condition.await();
}
// 满足条件进行一系列操作
... your operation
otherCondition.signal()// otherCondition.signalAll()
}catch(){
}finally{
lock.unlock();
}
区别notify、signal与notifyAll、signalAll
通过下一段代码来查看notify和notifyAll的区别。
import java.util.concurrent.TimeUnit;
/**
* Created by liukun on 18/10/4.
*/
public class Test {
private static Object object = new Object();
private static int value = 0;
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
final int tempi = i;
new Thread(new Runnable() {
@Override
public void run() {
function(tempi);
}
}).start();
}
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
value = 1;
synchronized (object) {
System.out.println("notify ------");
object.notifyAll();
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void function(int i) {
System.out.println("第" + i + "个 function被调用");
synchronized (object) {
System.out.println("第" + i + "个 进入synchronize");
while (value == 0) {
try {
System.out.println("第" + i + "个 准备wait");
object.wait();
System.out.println("第" + i + "个 被唤醒");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第" + i + "个 function要退出");
}
}
其中启动了5个线程,都处于wait的状态。然后main thread,调用了notify或者notifyAll。
输出情况:
调用notify的时候,只会有一个thread被唤醒(awakened)。当调用notifyAll的时候,会把所有都在等待对应这个object的monitor的threads都唤醒。
同理condition的signal和signalAll是一样的。