加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

【JUC】3.ReentrantLock

发布时间:2020-12-15 07:25:41 所属栏目:Java 来源:网络整理
导读:ReentrantLock实现Lock接口,所以先看下Lock接口: public interface Lock { // 获得锁 void lock(); // 获得锁 void unlock(); // lock非阻塞版本,成功返回true boolean tryLock(); // 添加尝试时间,时间到返回false boolean tryLock( long time,TimeUnit

ReentrantLock实现Lock接口,所以先看下Lock接口:

public interface Lock { // 获得锁
    void lock(); // 获得锁
    void unlock(); // lock非阻塞版本,成功返回true
    boolean tryLock(); // 添加尝试时间,时间到返回false
    boolean tryLock(long time,TimeUnit unit) // 返回一个监视器对象
 Condition newCondition(); }

再来看ReentrantLock的常用API:?

public class ReentrantLock implements Lock,Serializable { // 构造器,可以实现公平锁
    public ReentrantLock() public ReentrantLock(boolean fair) public void lock() // 可中断锁
    public void lockInterruptibly() // 可轮询的锁获取,有返回值。获取成功返回true;获取失败,返回false,线程不会阻塞、
    public boolean tryLock() public boolean tryLock(long timeout,TimeUnit unit) // 返回一个监视器对象
 Condition newCondition(); }?

ReentrantLock的使用方法分为这么几块:

1. 可重入锁的实现;

2. 公平锁与非公平锁;

3. 配合Condition实现的选择性通知,?condition实现阻塞队列,这两个可以视为同一块;

4.?tryLock的实现;

5.生产者消费者模式实现,如果用Condition实现这个模式,其实跟实现阻塞队列是类似的;

? ?同样也可以单纯使用阻塞队列实现生产者消费者模式;

可重入锁的实现

可以再次获取自己的内部锁,即:一个线程获取某对象锁,在没有释放此对象锁的同时,可以再次获得此锁;

锁释放请务必在finally中进行

public class ReentrantLockTest { private static final Lock lock = new ReentrantLock(); public static void test1() { lock.lock(); try { System.out.println("已进入test_1"); test2(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void test2() { lock.lock(); try { System.out.println("已进入test_2"); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } }

公平锁与非公平锁

只要在构造器中传入true,实现方面没什么好说的;

  • 非公平锁下的后来线程可以插队,减少了一定的线程上下文切换

  • 公平锁下后来的线程必须排队等待锁的释放,多进行了一步判断,线程挂起的几率比较高,所以效率略低

    满足FIFO(先进先出队列)

?非公平锁虽然效率高,但是有可能出现线程饿死的情况,比如客户端一直无法获得服务,所以,服务器一般用公平锁实现;

配合Condition实现的选择性通知

这个可以跟实现阻塞队列一起说了,感觉代码层面,基本一致;

?

public class MyBlockingQueue<T> {
    private int limit;
    private final Lock lock = new ReentrantLock();
    private final Condition Full = lock.newCondition();
    private final Condition Empty = lock.newCondition();
    private List<T> queue = new LinkedList<>();

    public MyBlockingQueue(int limit) {
        this.limit = limit;
    }

    public void enqueue(T item) throws InterruptedException {
        lock.lock();
        try {
            // 队列满
            while (queue.size() == limit) {
                Full.await();
            }
            queue.add(item);
            Empty.signal();
        } finally {
            lock.unlock();
        }
    }

    public T dequeue(T item) throws InterruptedException {
        lock.lock();
        try {
            // 队列空
            while (queue.size() == 0) {
                Empty.await();// 将当前线程阻塞在Empty监视器下
            }
            Full.signal(); // 叫醒Full监视器下阻塞的线程
            return queue.remove(0);
        } finally {
            lock.unlock();
        }
    }
}

tryLock的实现

tryLock方法可以无参,可以传入等待时间;

public class MytryLock {

    private static final Lock lock = new ReentrantLock();
    // 由于是否获得锁不确定,所以设置标志位判断
    private static boolean isLocked = false;

    public static void test() {
        try {
            if (lock.tryLock(1000,TimeUnit.MILLISECONDS)) {
                // trylock返回true,即拿到锁
                isLocked = true;
                System.out.println(Thread.currentThread().getName() + "拿到锁!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                /**
                 * 没拿到锁,可以让线程继续做别的事
                 * 不会阻塞
                 */
                System.out.println(Thread.currentThread().getName() + "没拿到锁!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (isLocked == true)
                lock.unlock();
        }
    }
}

生产者消费者模式实现

同condition实现阻塞队列;

queue就是生产者的仓库对象;

enqueue就是生产;

dequeue就是消费;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读