ReentrantLock锁特点以及演示

80 阅读2分钟

1.可中断

这个特点具体指的是,在线程尝试获得这个被其他线程拥有的锁的时候,会进入阻塞状态,这个ReentrantLock可以被其他线程打断等待的状态,进而退出阻塞等待的状态。具体使用见如下代码

package org.example.juclearning.learning02;
import java.util.concurrent.locks.ReentrantLock;
public class Ruse {
    static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                try {
                    lock.lockInterruptibly();
                    System.out.println("thread1获得锁了");
                } catch (InterruptedException e) {
                    System.out.println("t1被打断");
                    throw new RuntimeException(e);
                } finally {
                    lock.unlock();
                }
            }
        };
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                try {
                    lock.lockInterruptibly();
                    System.out.println("thread2 获得锁了");

                        for (int i = 0; i < 10; i++) {
                            Thread.sleep(100);
                            System.out.println("wwww" + i);
                            if(i == 5){
                                thread1.interrupt();
                            }
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    lock.unlock();
                }
            }
        };
        thread2.start();
        Thread.sleep( 1);
        thread1.start();
    }
}

在代码里面的24行,指明获取锁的时候是一个可以被打断的获取方式,在31行,其他线程成功执行了锁的打断。

2.可设置为公平锁

public ReentrantLock() {
    sync = new NonfairSync();
}

3.可以设置超时时间

package org.example.juclearning.learning02;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class Ruse02TryLock {
    static ReentrantLock lock = new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                try {
                    if (!lock.tryLock(1, TimeUnit.SECONDS)){
                        System.out.println("t1在一定时间内没有获得到锁");
                        return;
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                try {
                    System.out.println("t1成功地获得到了锁");
                }
                finally {
                    lock.unlock();
                }
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    if (!lock.tryLock(3, TimeUnit.SECONDS)) {
                        System.out.println("t2在一定时间内没有获得到锁");
                        return;
                    }
                    System.out.println("t2成功地获得到了锁");
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } finally {
                    lock.unlock();
                }
            }
        };
        t2.start();
        Thread.sleep(1000);
        t1.start();
    }
}

在11行的代码中,使用lock.tryLock方式获得锁,即表示在一定时间内还没有获得锁就会放弃获取。

4.支持多个条件变量(多个waitSet房间)

public class Rusr03Cond {
    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();
        Condition c3 = lock.newCondition();

        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c1.await();
                    System.out.println("1");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c1.await();
                    System.out.println("11");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c2.await();
                    System.out.println("2");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c2.await();
                    System.out.println("22");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c3.await();
                    System.out.println("3");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                try {
                    lock.lock();
                    c3.await();
                    System.out.println("33");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {
                    lock.unlock();
                }
            }
        }.start();
        System.out.println();
        lock.lock();
        try {
            c1.signalAll();
        }finally {
            lock.unlock();
        }
    }
}

个人是非常喜欢ReentranLock这个类的这个特点,相当于可以给这个锁设置了多个可以等待的房间,而不像wait方法,所有线程都集中在一个房间中。这样的话可以进行有针对性的唤醒动作,进而可以避免虚假唤醒的情况。