ReentrantLock 在使用上比synchronized稍微复杂点,需要显示的获取锁和释放锁。
synchronized属于非公平锁,当多个线程去竞争同一个锁时,具体哪个线程会获取到锁不确定。ReentrantLock 除了支持非公平锁外,还支持公平锁,即获取锁的先后顺序已经确定,后来的会排到最后。
基本使用形式:
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
System.out.println("do something");
} finally {
lock.unlock();
}
常用的四个方法:
lock.lock() 获取锁
lock.unLock() 释放锁
lock.tryLock() 立即去获取锁,获取到返回true,获取不到返回false
lock.tryLock(TimeOut,TimeUnit) 在一段时间内尝试获取锁,在这段时间内获取到了锁,返回true,超时后返回false。
以上四个方法的使用:
1.初始化lock对象
ReentrantLock lock = new ReentrantLock();
2.在线程t1中使用锁,获取锁后休眠3秒。休眠完后,释放锁
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
lock.lock();
System.out.println(Thread.currentThread().getName() + " lock success");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
System.out.println(Thread.currentThread().getName()+" unlock");
lock.unlock();
}
}
});
3.在线程t2中尝试获取锁,成功失败都打印相应信息。
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
if (lock.tryLock(1, TimeUnit.SECONDS)) {
System.out.println(Thread.currentThread().getName() + " tryLock success");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + "tryLock failure");
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("等待获取锁时被打断");
}
}
});
4.确保t1先执行,再执行t2。
t1.start();
TimeUnit.SECONDS.sleep(1);
t2.start();
4.1 tryLock等待时间超时的情况。
t1先执行,拿到锁后立刻休眠三秒。t1执行一秒后,t2执行。这时t2 tryLock(1, TimeUnit.SECONDS),由于在这一秒内,锁一直被t1持有,
超时后拿不到锁,故打印:Thread-1tryLock failure。之后t1休眠完毕,释放锁。
Thread-0 lock success
Thread-1tryLock failure
Thread-0 unlock
4.2 tryLock成功获取到锁的情况。
修改等待获取锁的时间,即if (lock.tryLock(3, TimeUnit.SECONDS))。
由于t2 tryLock等待的时间足够长,当t1执行完毕后释放了锁,这时,还在t2 tryLock等待时间之内,所以会立即获取锁。
Thread-0 lock success
Thread-0 unlock
Thread-1 tryLock success
可见ReentrantLock功能更多,当sychronized不能满足需求时,可以使用ReentrantLock。
网友评论