https://blog.csdn.net/luzhouyue1024/article/details/128589928
Java使用synchronized关键字实现了临界代码区的原子性与可见性并发安全,为什么还需要Lock类呢?https://blog.csdn.net/luzhouyue1024/article/details/128589928
在"Java Concurrency in Practice"一书中,作者提到,“内置锁synchronized无法中断一个正在等待获取锁的线程,并无法实现非阻塞结构的加锁规则”。
下面用一个实验展示synchronized非阻塞的行为.
package lydia.study.concurrent;
public class SynchronizedTest {
//测试synchronized不响应中断
public static void testSynchronized() {
Object o = new Object();
Thread t1 = new Thread(){
public void run () {
synchronized (o) {
try {
System.out.println("Thread t1 get the synchronized lock");
Thread.sleep(5000);
System.out.println("Thread t1结束休眠");
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
System.out.println("Thread t1退出");
}
}
}
};
t1.start();
Thread t2 = new Thread() {
public void run() {
synchronized (o) {
System.out.println("Thread t2 get the synchronized lock");
}
}
};
t2.start();
System.out.println("尝试对线程2中断");
t2.interrupt();
System.out.println("main结束");
}
public static void main(String[] args) throws InterruptedException {
testSynchronized();
}
}
运行结果如下
尝试对线程2中断
main结束
Thread t1 get the synchronized lock
Thread t1结束休眠
Thread t1退出
Thread t2 get the synchronized lock
线程t1先创建并运行,获取synchronized锁,然后休眠5秒钟;此时线程t2也被创建,它1同样想获取synchronized锁,但是由于锁在t1手中,只能等待t1结束运行再获得锁并打印出"Thread t2 get the synchronized lock"。注意,主线程尝试了以下这句代码,想中断t2,但是t2并没有响应中断。
t2.interrupt();
为了使得一个线程在等待锁的时候,能够响应中断,Lock接口的lockInterruptibly()方法提供了可响应中断的行为。让我们看下一个实验
package lydia.study.concurrent;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
//lock的interruptibly在线程阻塞并等待锁的时候,能响应中断
public static void lockInterruptibly() throws InterruptedException {
Object o = new Object();
Lock lockO = new ReentrantLock();
Thread t1 = new Thread(){
public void run () {
{
try {
lockO.lockInterruptibly();
System.out.println("Thread t1 get the lock");
Thread.sleep(5000);
System.out.println("Thread t1结束休眠");
} catch (InterruptedException e) {
System.out.println("Thread t1被中断");
e.printStackTrace();
} finally {
lockO.unlock();
System.out.println("Thread t1退出");
}
}
}
};
t1.start();
Thread t2 = new Thread() {
public void run() {
try {
lockO.lockInterruptibly();
System.out.println("线程t2 get the lockO");
}catch (InterruptedException e) {
System.out.println("Thread t2被中断");
e.printStackTrace();
} finally {
lockO.unlock();
System.out.println("Thread t2退出");
}
}
};
Thread.sleep(1000);
t2.start();
System.out.println("尝试对线程2中断");
t2.interrupt();
System.out.println("main结束");
}
public static void main(String[] args) throws InterruptedException {
lockInterruptibly();
}
}
运行,会得到以下结果
Thread t1 get the lock
尝试对线程2中断
main结束
Thread t2被中断
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
......
at lydia.study.concurrent.LockTest$2.run(LockTest.java:41)
Thread t1结束休眠
Thread t1退出
在lockInterruptibly()测试方法中,可以看到t2响应了中断,立刻返回,不再等待 lock的锁。