ReentrantLock特性
- 可中断
- 可以设置超时时间
- 可以设置公平锁
- 支持多个条件变量
- 支持重入,和synchronized一致
基本语法
// 基于ReentrantLock对象保护临界区
reentarntLock.lock();
try{
// 临界区
}finally{
// rnnetrantLock.unlock();
}
可重入
- 可重入指同一线程如果首次获得了这把锁,如果在获取再获取这把锁,表示可重入
可打断
- lockInterruptibly() 锁可打断
- 如果没有竞争,就会获取lock对象锁
- 如果有竞争就会进入阻塞队列
- 可以被其他线程用interrupt方法打断
锁超时
- tryLock() 尝试获得锁
- 使用tryLock()解决哲学家就餐问题,tryLock()返回false说明没能获得锁
public class PhilosopherProblem {
public static void main(String[] args) {
Chopstic c1 = new Chopstic("1");
Chopstic c2 = new Chopstic("2");
Chopstic c3 = new Chopstic("3");
Chopstic c4 = new Chopstic("4");
Chopstic c5 = new Chopstic("5");
new Philosopher("苏格拉底",c1,c2).start();
new Philosopher("泊拉图",c2,c3).start();
new Philosopher("亚里士多德",c3,c4).start();
new Philosopher("阿基米德",c4,c5).start();
new Philosopher("米开朗琪罗",c5,c1).start();
}
}
@Slf4j(topic = "ants.Philosopher")
class Philosopher extends Thread{
Chopstic left;
Chopstic right;
public Philosopher(String name,Chopstic left,Chopstic right){
super(name);
this.left = left;
this.right = right;
}
@SneakyThrows
@Override
public void run() {
while (true){
// synchronized (left){
// synchronized (right){
// eat();
// }
// }
if(left.tryLock()){
try{
if(right.tryLock()){
try{
eat();
}finally {
right.unlock();
}
}
}finally {
left.unlock();
}
}
}
}
private void eat() throws InterruptedException {
log.debug("eating...");
Thread.sleep(1000);
}
}
class Chopstic extends ReentrantLock {
private String name;
public Chopstic(String name){
this.name = name;
}
@Override
public String toString() {
return "筷子:【"+name+"】";
}
}
公平锁
- ReentrantLock默认是非公平锁,当构造函数时true,使用公平锁
- 公平锁可以解决姐问题
- 平时不设置,公平锁降低并发度
条件变量
ReentrantLock支持多个条件变量,想比synchronized的waitset
- synchronized不满足条件的变量都会放在同一个waitset中
- ReentrantLock中的条件变量支持多个条件变量,一个条件变量想当与一个waitset
- 使用流程
- await前需要获得锁
- await执行后,会释放锁,进入conditionObject等待
- await的线程被唤醒singnal(打断、超时)时重新竞争lock锁
- 竞争lock锁成功后,从await后继续执行
@Slf4j(topic = "ants.ManyCondition")
public class ManyCondition {
static volatile boolean t1Status;
static volatile boolean t2Status;
static ReentrantLock lock = new ReentrantLock();
static Condition sta1 = lock.newCondition();
static Condition sta2 = lock.newCondition();
public static void main(String[] args) {
new Thread("t1") {
@SneakyThrows
@Override
public void run() {
lock.lock();
try {
while (!t1Status) {
sta1.await();
}
log.debug("t1干了剩下的活");
} finally {
lock.unlock();
}
}
}.start();
new Thread("t2") {
@SneakyThrows
@Override
public void run() {
lock.lock();
try {
while (!t2Status) {
sta2.await();
}
log.debug("t2干了剩下的活");
} finally {
lock.unlock();
}
}
}.start();
lock.lock();
try {
sta1.signal();
t1Status = true;
} finally {
lock.unlock();
}
}
}
网友评论