Java ReentrantLock

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

原文地址:https://www.cnblogs.com/lvjianwei/p/8442221.html