在讲重入锁(ReentrantLock)之前,相信大家都synchronized很熟悉了,它也是同步控制的一个重要锁,决定了一个线程
是否可以访问临界资源,同时synchronized配合Object.wait()和Object.notify()的配合使用起到了等待通知的作用。这里如果
大家不是很熟悉,可以查阅资料熟悉一下synchronized的使用。那么有synchronized这个锁,为什么还要介绍ReentrantLock,
这肯定是有原因,接下来我就会介绍ReentrantLock比synchronized锁的优点。再说到优点之前,我们先看看ReentrantLock的
基本使用。
(一)ReenrantLock的基本使用
public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
public static int i =0;
@Override
public void run() {
for(int j = 0;j<10000;j++){
lock.lock();
try {
i++;
}
finally{
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 =new Thread(t);
Thread t2 =new Thread(t);
t1.start();t2.start();
t1.join();t2.join();
System.out.println(i);
}
}
通过上面代码我们可以看到ReentrantLock的lock()和unlock()方法要配合try/finally语句块来完成,这是ReentrantLock的语法风格,
lock.lock();
lock.lock();
try{
i++;
}finally{
lock.unlock();
lock.unlock();
}
在这种情况下,一个线程连续两次获得同一把锁,是允许,如果不允许这么操作,那么同一个线程在第二次获得锁时,将会与自己(二)ReetrantLock的高级功能
- 可以中断响应
public class ReenterLock implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public ReenterLock(int lock){
this.lock = lock;
}
@Override
public void run() {
try{
if (lock == 1){
lock1.lockInterruptibly();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
lock2.lockInterruptibly();}
else{
lock2.lockInterruptibly();
try{
Thread.sleep(500);
}catch(InterruptedException e){}
lock1.lockInterruptibly();
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
if(lock1.isHeldByCurrentThread())
lock1.unlock();
if(lock2.isHeldByCurrentThread())
lock2.unlock();
System.out.println(Thread.currentThread().getId()+":线程退出");
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock r1 = new ReenterLock(1);
ReenterLock r2 = new ReenterLock(2);
Thread t1 =new Thread(r1);
Thread t2 =new Thread(r2);
t1.start();t2.start();
Thread.sleep(1000);
t2.interrupt();
}
}
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:896)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1221)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:340)
at demo.ReenterLock.run(ReenterLock.java:29)
at java.lang.Thread.run(Thread.java:745)
10:线程退出
9:线程退出
- 锁等待限时
public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
try{
if(lock.tryLock(5, TimeUnit.SECONDS))
Thread.sleep(6000);
else{
System.out.println("get this lock fialed");
}
}catch(InterruptedException e){
e.printStackTrace();
}finally{
if(lock.isHeldByCurrentThread())
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();t2.start();
}
}
在这里,tryLock()方法接受两个参数,一个表示等待时长,另外一个表示计时单位。这里的单位为秒,时长为5,表示线程- 公平锁
public class ReenterLock implements Runnable{
public static ReentrantLock fairlock = new ReentrantLock(true);//设置为true开启公平锁,默认是false
@Override
public void run() {
while(true){
try{
fairlock.lock();
System.out.println(Thread.currentThread().getName()+"获得锁");
}finally{
fairlock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t,"Thread_1");
Thread t2 = new Thread(t,"Thread_2");
t1.start();t2.start();
}
}
上面代码在通过ReentranLock(boolean fair)设置为true开启公平锁,接下来看看结果:Thread_1获得锁
Thread_2获得锁
Thread_1获得锁
Thread_2获得锁
Thread_1获得锁
Thread_2获得锁
Thread_1获得锁
Thread_2获得锁
Thread_1获得锁
由于代码有大量的输出,这里只截取部分进行说明。这个输出结果中,很明显可以看到,两个线程是交替执行的。(三)Condition条件
如果大家知道Object.wait 和 Object.notify方法的话,那么就能很容易理解Condition 了,它们的作用大致相同的。public class ReenterLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
public static Condition condition = lock.newCondition();
@Override
public void run() {
try{
lock.lock();
condition.await();
System.out.println("Thread is going on");
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
ReenterLock t = new ReenterLock();
Thread t1 = new Thread(t);
t1.start();
Thread.sleep(2000);
//通知线程t1继续执行
lock.lock();
condition.signal();
lock.unlock();
}
}
代码第三行,通过lock生成一个与之绑定的Condition对象。代码condition.await(),要求线程Condition对象上进行等待。