1、内置锁的局限
一个线程因为等待内置锁而进入阻塞状态,就无法终端该线程了
尝试获取内置锁时无法设置超时时间
获取内置锁,必须使用synchronized块,如下
synchronized(object){
《使用共享资源》
}
,这种用法的限制是获取锁和释放锁的代码必须严格嵌在同一个方法里面
与synchronized不同的时java.util.concurrent包中得ReentrantLock类提供了现实的lock和unlock方法,可以突破以上几个限制。
2、ReentrantLock类
首先,看一下RenntrantLock如何代替synchronized工作的:
Lock lock = new ReentrantLock();
lock.lock();
try{
//使用共享资源
}catch(Exception e){
}finally {
lock.unlock();
}
这个例子中使用try ... finally是个很好的实践,无论被锁保护的代码发生了什么,都可以确保锁会被释放。
3、ReentrantLock中断阻塞的线程
package com.paulbutcher;
public class Uninterruptible {
public static void main(String[] args) throws Exception {
final Object obj1 = new Object();
final Object obj2 = new Object();
Thread thread1 = new Thread(){
public void run(){
try{
synchronized(obj1){
Thread.sleep(1000);
synchronized(obj2){}
}
}catch(Exception e){
System.out.println("thread1 interruptible");
}
}
};
Thread thread2 = new Thread(){
public void run(){
try{
synchronized(obj2){
Thread.sleep(1000);
synchronized(obj1){}
}
}catch(Exception e){
System.out.println("thread2 interruptible");
}
}
};
thread1.start();
thread2.start();
Thread.sleep(2000);
thread1.interrupt();
thread2.interrupt();
thread1.join();
thread2.join();
}
}
这段代码将永远的死锁下去-------跳出死锁的唯一办法就是终止JVM的运行。
我们可以使用ReetrantLock代替内置锁,使用其中的lockInterruptibly()方法:
package com.paulbutcher;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Interruptible {
public static void main(String[] args) throws Exception {
final Lock lock1 = new ReentrantLock();
final Lock lock2 = new ReentrantLock();
Thread thread1 = new Thread(){
public void run(){
try{
lock1.lockInterruptibly();
Thread.sleep(1000);
lock2.lockInterruptibly();
}catch(Exception e){
System.out.println("thread1 interruptible");
}
}
};
Thread thread2 = new Thread(){
public void run(){
try{
lock2.lockInterruptibly();
Thread.sleep(1000);
lock1.lockInterruptibly();
}catch(Exception e){
System.out.println("thread2 interruptible");
}
}
};
thread1.start();
thread2.start();
Thread.sleep(2000);
thread1.interrupt();
thread2.interrupt();
thread1.join();
thread2.join();
}
}
这个时候,我们就可以使用interrupt()方法中断该线程了
4、ReetrantLock设置超时时间
package com.paulbutcher;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Interruptible {
public static void main(String[] args) throws Exception {
final Lock lock1 = new ReentrantLock();
final Lock lock2 = new ReentrantLock();
Thread thread1 = new Thread(){
public void run(){
try{
lock1.lockInterruptibly();
Thread.sleep(1000);
lock2.tryLock(1000, TimeUtil.MILLISECONDS);
}catch(Exception e){
System.out.println("thread1 interruptible");
}
}
};
Thread thread2 = new Thread(){
public void run(){
try{
lock2.lockInterruptibly();
Thread.sleep(1000);
lock1.tryLock(1000, TimeUtil.MILLISECONDS);
}catch(Exception e){
System.out.println("thread2 interruptible");
}
}
};
thread1.start();
thread2.start();
Thread.sleep(2000);
thread1.interrupt();
thread2.interrupt();
thread1.join();
thread2.join();
}
}
这样,也不会发生死锁了