JUC简笔3-ReentranLock的组成与使用

1、什么是ReentranLock?

ReentranLock,是一个可重入的互斥锁,又被称为“独占锁”;ReentrantLock锁在同一个时间点只能被一个线程锁持有;而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取。

2、ReentranLock的组成

继承关系:实现Lock接口;
通过Sync类(Sync类继承于AQS)实现同步状态更新,它有FairSync和NonFairSync两个具体实现类来实现公平锁和非公平锁;

public class ReentrantLock implements Lock, java.io.Serializable {
    //内部类Sync,继承自AQS
    private final Sync sync;
    abstract static class Sync extends AbstractQueuedSynchronizer {...}

    //非公平锁
    static final class NonfairSync extends Sync {...}

    //公平锁
    static final class FairSync extends Sync {...}

    //构造方法,Sync默认为非公平锁
    public ReentrantLock() {
        sync = new NonfairSync();
    }

    //带参构造方法,true为公平锁,false为非公平锁
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    //下面还有一大堆方法...

3、ReentranLock用法示例

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Depot {
    //仓库产品的数量 
    private int size;
    //独占锁
    private Lock lock;

    //无参构造方法
    public Depot() {
        this.size = 0;
        this.lock = new ReentrantLock();
    }

    public void produce(int val) {
        lock.lock();
        try {
            size = size + val;
            System.out.println(Thread.currentThread().getName()
                    + " produce:" + val + " size:" + size);
        } finally {
            lock.unlock();
        }       
    }

    public void consume(int val) {
        lock.lock();
        try {
            size = size - val;
            System.out.println(Thread.currentThread().getName()
                    + " consume:" + val + " size:" + size);
        } finally {
            lock.unlock();
        }
    }   
}

//生产者
class Producer {
    private Depot depot;

    public Producer(Depot depot) {
        this.depot = depot;
    }

    //新建一个线程在仓库中生产产品
    public void produce(int val) {      
        new Thread() {
            public void run() {
                depot.produce(val);
            }
        }.start();
    }   
}

class Consumer {
    private Depot depot;

    public Consumer(Depot depot) {
        this.depot = depot;
    }

    //新建一个线程在仓库中消费产品
    public void consume(int val) {
        new Thread() {
            public void run() {
                depot.consume(val);
            }
        }.start();
    }
}

public class Test1 {
    public static void main(String[] args) {
        Depot depot = new Depot();
        Consumer consumer = new Consumer(depot);
        Producer producer = new Producer(depot);
        producer.produce(60);
        producer.produce(120);
        consumer.consume(90);
        consumer.consume(150);
        producer.produce(110);

    }
}

运行结果截图:
《JUC简笔3-ReentranLock的组成与使用》
可以看出,ReentranLock通过lock.lock()和lock.unlock()两个方法获取锁和释放锁,与synchronized作用相似,可以保证每次只有一个线程获取到锁。

PS:上面的例子只用于展示ReentranLock的基本使用,存在部分一些不合实际的情况,如仓库没有做负数检测也没有做容量检测,运行时就有可能出现下面这种不合实际的情况。
《JUC简笔3-ReentranLock的组成与使用》

参考资料
Java多线程系列–“JUC锁”02之 互斥锁ReentrantLock——http://www.cnblogs.com/skywang12345/p/3496101.html

    原文作者:JUC
    原文地址: https://blog.csdn.net/weixin_38278878/article/details/80202897
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞