40 多线程(十二)——ReentrantLock 可重入锁
我们使用的synchronized加的锁是可以延续使用的,如下:
public void test() { //第一次获得锁 synchronized(this) { while(true) { //第二次获得同样的锁 synchronized(this) { System.out.println("ReentrantLock"); } try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
使用synchronized加的锁必须等到线程结束才会被释放,这可能会造成死锁。
而相对synchronized,ReentrantLock锁更灵活,它可以指定加锁一段时间后主动释放锁等更为强大的功能,目前仅做了解即可。
详细内容自行百度。接下来仿写ReentrantLock源码,实现基本的lock与unLock方法。
package _20191209; /** * 可重入锁演示:锁不以延续使用 * @author TEDU * */ public class LockTest03 { ReLock lock = new ReLock(); public void a() throws InterruptedException { lock.lock(); System.out.println(lock.getHoldCount()); doSomething();//需要被加锁的部分 lock.unlock(); System.out.println(lock.getHoldCount()); } public void doSomething() throws InterruptedException { lock.lock(); System.out.println(lock.getHoldCount()); //。。。。。。 lock.unlock(); System.out.println(lock.getHoldCount()); } public static void main(String[] args) throws InterruptedException { LockTest03 test = new LockTest03(); test.a(); } } //可重入锁 class ReLock{ //是否被占用 private boolean isLocked = false; //存储线程的变量 private Thread lockedBy = null; //锁计数器:锁使用次数 private int holdCount = 0; //使用锁 public synchronized void lock() throws InterruptedException{ Thread t = Thread.currentThread(); while(isLocked && lockedBy != t) { wait(); } isLocked = true; lockedBy = t; holdCount ++; } //释放锁 public synchronized void unlock() { if(Thread.currentThread() == lockedBy) { holdCount --; if(holdCount == 0) { isLocked = false; notify(); lockedBy = null; } } } public int getHoldCount() { return holdCount; } }
如果需要使用ReentrantLock只需要new一个就行了:
ReentrantLock relock = new ReentrantLock(); relock.lock();//加锁 relock.unlock();//解锁