显示锁ReentrantLock和Condition的使用
阅读原文时间:2023年07月09日阅读:1

一、ReentrantLock
(1)、java.util.concurrent.locks包中的ReentrantLock就是重入锁,它实现了Lock接口,Lock加锁和解锁都是显示的。ReentrantLock重入锁可以实现synchronized关键字的功能。
主要方法:
lock:获得锁。
unlock:释放锁。
(2)、java对synchronized优化之后,ReentrantLock和synchronize大的区别:
a、锁的粒度,ReentrantLock更细,更灵活。
b、ReentrantLock可以指定锁的公平性。synchronize只能是非公平的。
c、ReentrantLock可以利用Condition(条件)类选择性分组唤醒线程。
d、ReentrantLock可以中断一个正在等待获取锁的线程。lockInterruptibly()。
(3)、典型的使用格式:

class X {
private final ReentrantLock lock = new ReentrantLock();
// …
public void m() {
lock.lock(); // block until condition holds
try {
// … method body
} finally {
lock.unlock()
}
}
}

测试i++的代码:
注意:必须在finally块中调用unlock语句释放锁,以确保即使在方法体中抛出异常(try块)锁也会释放锁。否则这个锁永远不释放。

/**
* @author monkjavaer
* @date 2018/12/16 22:24
*/
public class ReentrantLockService{

private Lock lock = new ReentrantLock();  
private int count = 0;

public void getCount(){  
    try {  
        //获得锁  
        lock.lock();  
        System.out.println("thread :"+Thread.currentThread().getName()+" count = "+count++);  
    } catch (Exception e) {  
        e.printStackTrace();  
    }finally {  
        //在finally块中调用unlock语句,以确保即使在方法体中抛出异常(try块)也会释放锁。  
        lock.unlock();  
    }  
}

public static void main(String\[\] args) {  
    ReentrantLockService service = new ReentrantLockService();  
    for(int i=0; i<100; i++){  
        new Thread("" + i){  
            @Override  
            public void run(){  
                service.getCount();  
            }  
        }.start();  
    }  
}

}

二、Condition
(1)、Condition通过Lock对象调用newCondition()方法获得。借助Lock,Condition可以实现wait && notify同样的功能。主要方法:
await(): 使当前线程等待
signal():唤醒一个等待的线程
signalAll():唤醒所有等待的线程
(2)、在使用Condition的方法时需要先获得锁,即调用Lock对象的lock()方法,否则会抛出IllegalMonitorStateException,因为没有监视器对象。

Condition使用实例:

/**
* @author monkjavaer
* @date 2018/12/18 21:14
*/
public class ConditionService {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();

public void awaitTest(){  
    try {  
        lock.lock();  
        System.out.println("before await()");  
        condition.await();  
        System.out.println("after await()");  
    } catch (InterruptedException e) {  
        e.printStackTrace();  
    }finally {  
        lock.unlock();  
    }  
}

public void signalTest(){  
    try {  
        lock.lock();  
        System.out.println("before signal()");  
        condition.signal();  
        System.out.println("after signal()");  
    } catch (Exception e) {  
        e.printStackTrace();  
    }finally {  
        lock.unlock();  
    }  
}

public static void main(String\[\] args) {  
    ConditionService service = new ConditionService();  
    Thread thread1 = new Thread(new Runnable() {  
        @Override  
        public void run() {  
            service.awaitTest();  
        }  
    });  
    thread1.start();

    Thread thread2 = new Thread(new Runnable() {  
        @Override  
        public void run() {  
            service.signalTest();  
        }  
    });  
    thread2.start();  
}  

}