import
java.util.concurrent.locks.Lock;
import
java.util.concurrent.locks.ReentrantLock;
public
class
Test
extends
Thread {
private
static
Lock lock =
new
ReentrantLock();
@Override
public
void
run() {
try
{
// 以可中断方式申请锁, 在申请锁的过程中如果当前线程被中断,将抛出InterruptedException异常
lock.lockInterruptibly();
}
catch
(InterruptedException e) {
System.out.println(
"interruption happened"
);
return
;
}
// 如果运行到这里, 说明已经申请到锁, 且没有发生异常(没有被中断)
try
{
System.out.println(
"run is holding the lock"
);
}
finally
{
lock.unlock();
}
}
public
static
void
main(String[] args)
throws
InterruptedException {
try
{
lock.lock();
//主线程一开始就持有锁,所以子线程申请锁的时候被阻塞
Thread thread =
new
Test();
thread.start();
// 1s后中断thread线程, 该线程此时应该阻塞在lockInterruptibly方法上
Thread.sleep(
1000
);
// 中断thread线程将导致其抛出InterruptedException异常.
thread.interrupt();
Thread.sleep(
1000
);
}
finally
{
lock.unlock();
}
}
}
对于内置锁,只要代码运行到同步代码块之外,就会自动释放锁,开发者无需担心抛出异常,方法返回等情况发生时锁会没有被释放的问题。然而对于显式锁,必须调用unlock方法才能释放锁。此时需要开发者自己处理抛出异常, 方法返回等情况。通常会在finally代码块中进行锁的释放, 还需注意只有申请到锁之后才需要释放锁, 释放未持有的锁可能会抛出未检查异常。
所以使用内置锁更容易一些, 而显式锁则繁琐很多. 但是显式锁释放方式的繁琐也带来一个方便的地方: 锁的申请和释放不必在同一个代码块中,但必须在同一个线程中,不可以释放别的线程持有的锁。
4)公平锁
通过ReentrantLock(boolean fair)构造函数创建ReentrantLock锁时可以为其指定公平策略, 默认情况下为不公平锁.
多个线程申请公平锁时, 申请时间早的线程优先获得锁. 然而不公平锁则允许插队, 当某个线程申请锁时如果锁恰好可用, 则该线程直接获得锁而不用排队. 比如线程B申请某个不公平锁时该锁正在由线程A持有, 线程B将被挂起. 当线程A释放锁时, 线程B将从挂起状态中恢复并打算再次申请(这个过程需要一定时间). 如果此时恰好线程C也来申请锁, 则不公平策略允许线程C立刻获得锁并开始运行. 假设线程C在很短的一段时间之后就释放了锁, 那么可能线程B还没有完成恢复的过程. 这样一来, 节省了线程C从挂起到恢复所需要的时间, 还没有耽误线程B的运行. 所以在锁竞争激烈时, 不公平策略可以提高程序吞吐量.
内置锁采用不公平策略, 而显式锁则可以指定是否使用不公平策略
5)唤醒和等待(同步)线程可以wait在内置锁上, 也可以通过调用内置锁的notify或notifyAll方法唤醒在其上等待的线程。但是如果有多个线程在内置锁上wait, 我们无法精确唤醒其中某个特定的线程。
显式锁也可以用于唤醒和等待。调用lock.newCondition()方法可以创建一个Condition对象,调用condition.await()方法将使得线程等待,调用condition.singal()或condition.singalAll()方法可以唤醒在该condition对象上等待的线程。由于同一个显式锁可以创建多个Condition对象,不同的线程可以在不同的Condition对象上等待,因此我们可以实现精确唤醒某个线程。大致用法:
创建Condition对象:
private
Condition c1 = lock.newCondition();
private
Condition c2 = lock.newCondition();
private
Condition c3 = lock.newCondition();
线程2可以调用下面语句等待:
c2.await();线程3可以调用下面语句等待:
c3.await();版权声明:本文为博主原创文章,未经博主允许不得转载。