ReentrantLock是Lock接口的实现,除了实现Lock接口的功能,还提供了getHoldCount()和getQueueLengt()两个方法,分别用于获取目前加锁数量和等待获取锁队列的长度。
使用的时候,要保证加锁必须有解锁,否则会导致死锁,为了保证最后能够解锁,一定要在最后使用finally将unlock方法紧紧裹住。
class X { private final ReentrantLock lock = new ReentrantLock(); // ... public void m() { lock.lock(); // block until condition holds try { // ... method body } finally { lock.unlock() } } }
/** * Created by LvJianwei on 2018/2/9. */ import java.util.concurrent.locks.ReentrantLock; import static sun.misc.Version.println; /** * @program: ReentrantLockDemo * @description: ReentrantLockDemo * @author: LvJianwei * @create: 2018-02-09 14:41 **/ public class ReentrantLockDemo { public static void main(String[] args) { ReentrantLockDemo demo = new ReentrantLockDemo(); Runnable rAdd = () -> { try { Thread.sleep(1000); demo.countAdd(); } catch (InterruptedException e) { e.printStackTrace(); } }; Runnable rReduce = () -> { try { Thread.sleep(1000); demo.countReduce(); } catch (InterruptedException e) { e.printStackTrace(); } }; for (int i = 0; i < 5; i++) { Thread t = new Thread(rReduce); t.start(); } for (int i = 0; i < 5; i++) { Thread t = new Thread(rAdd); t.start(); } } private ReentrantLock locker = new ReentrantLock(); public int count = 0; public void caculateWithoutLock() { countAdd(); countReduce(); } public synchronized void caculate() { countAdd(); countReduce(); printLockStatus(); longTimeLock(); } public void caculateWithLock() { locker.lock(); locker.getHoldCount(); try { countAdd(); countReduce(); printLockStatus(); longTimeLock(); } finally { locker.unlock(); } } public void countAdd() { locker.lock(); try { count++; System.out.printf("Add,count:%d ", count); printLockStatus(); longTimeLock(); } finally { locker.unlock(); } } public void countReduce() { locker.lock(); try { count--; System.out.printf("reduce,count:%d ", count); printLockStatus(); longTimeLock(); } finally { locker.unlock(); } printLockStatus(); } public void longTimeLock() { locker.lock(); try { int locktime = 3000; System.out.printf("longTimeLock:%d ms ", locktime); printLockStatus(); Thread.sleep(locktime); } catch (InterruptedException e) { e.printStackTrace(); } finally { locker.unlock(); } printLockStatus(); } private void printLockStatus() { System.out.printf("thread id:%d,lock count:%d,queueLength:%d ", Thread.currentThread().getId(), locker.getHoldCount(), locker.getQueueLength()); } }
countAdd方法和countReduce争夺count的计算,由于加锁,不论如何运行,最终结果都是0。
同一个线程可以添加多个锁,但是必须都要解锁才能释放,代码中增加一个longTimeLock用于多加一把锁,每一个线程执行的时候都会输出当前锁的数量和排队线程的数量,随着程序的执行,排队数量逐渐减少。
Add,count:1
thread id:17,lock count:1,queueLength:9
longTimeLock:3000 ms
thread id:17,lock count:2,queueLength:9
thread id:17,lock count:1,queueLength:9
thread id:17,lock count:0,queueLength:9
-----------------------
reduce,count:0
thread id:11,lock count:1,queueLength:8
longTimeLock:3000 ms
thread id:11,lock count:2,queueLength:8
thread id:11,lock count:1,queueLength:8
reduce,count:-1
thread id:15,lock count:1,queueLength:7
longTimeLock:3000 ms
thread id:15,lock count:2,queueLength:7
thread id:11,lock count:0,queueLength:7
-----------------------
thread id:15,lock count:1,queueLength:7
thread id:15,lock count:0,queueLength:7
-----------------------
reduce,count:-2
thread id:13,lock count:1,queueLength:6
longTimeLock:3000 ms
thread id:13,lock count:2,queueLength:6
thread id:13,lock count:1,queueLength:6
thread id:13,lock count:0,queueLength:6
-----------------------
reduce,count:-3
thread id:14,lock count:1,queueLength:5
longTimeLock:3000 ms
thread id:14,lock count:2,queueLength:5
thread id:14,lock count:1,queueLength:5
thread id:14,lock count:0,queueLength:5
-----------------------
Add,count:-2
thread id:18,lock count:1,queueLength:4
longTimeLock:3000 ms
thread id:18,lock count:2,queueLength:4
thread id:18,lock count:1,queueLength:4
thread id:18,lock count:0,queueLength:4
-----------------------
Add,count:-1
thread id:16,lock count:1,queueLength:3
longTimeLock:3000 ms
thread id:16,lock count:2,queueLength:3
thread id:16,lock count:1,queueLength:3
thread id:16,lock count:0,queueLength:3
-----------------------
reduce,count:-2
thread id:12,lock count:1,queueLength:2
longTimeLock:3000 ms
thread id:12,lock count:2,queueLength:2
thread id:12,lock count:1,queueLength:2
thread id:12,lock count:0,queueLength:2
-----------------------
Add,count:-1
thread id:20,lock count:1,queueLength:1
longTimeLock:3000 ms
thread id:20,lock count:2,queueLength:1
thread id:20,lock count:1,queueLength:1
thread id:20,lock count:0,queueLength:1
-----------------------
Add,count:0
thread id:19,lock count:1,queueLength:0
longTimeLock:3000 ms
thread id:19,lock count:2,queueLength:0
thread id:19,lock count:1,queueLength:0
thread id:19,lock count:0,queueLength:0
-----------------------
Process finished with exit code 0