java并发编程中的ReentrantLock

Posted 湾岸技研 Wangan Tech

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发编程中的ReentrantLock相关的知识,希望对你有一定的参考价值。

package com.wangan.logistic;

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

public class WanganReentrantLockService {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    
    private void await() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "线程获得了lock");
            System.out.println(Thread.currentThread().getName() + "线程await,暂交出锁,并进入等待队列");
            condition.await();
            System.out.println(Thread.currentThread().getName() + "线程被从await唤醒,获得之前交出的锁并继续执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + "线程释放了lock");
        }
    }
    
    private void signal() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + "线程获得了lock");
            condition.signal();
            System.out.println(Thread.currentThread().getName() + "线程发出signal,非公平唤醒等待队列中的其他线程");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + "线程释放了锁");
        }
    }
    
    
    public static void main(String[] args) {
        WanganReentrantLockService service = new WanganReentrantLockService();
        new Thread(new Runnable() {
            @Override
            public void run() {
                /*
                 * 这块可以模拟一下如果这个线程比main线程跑的慢,会发生什么
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                */
                service.await();
            }
        }).start();
        try {
            Thread.sleep(3000);    //防止main线程跑得比Thread-0还快
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        service.signal();
    }
}

控制台输出:

Thread-0线程获得了lock
Thread-0线程await,暂交出锁,并进入等待队列
main线程获得了lock
main线程发出signal,非公平唤醒等待队列中的其他线程
main线程释放了锁
Thread-0线程被从await唤醒,获得之前交出的锁并继续执行
Thread-0线程释放了lock

程序进程执行完毕,进程正常结束。

如果把代码中注释掉的部分放开,故意让new出来的线程跑的比main线程慢的话,控制台输出:

main线程获得了lock
main线程发出signal,非公平唤醒等待队列中的其他线程
main线程释放了锁
Thread-0线程获得了lock
Thread-0线程await,暂交出锁,并进入等待队列

此时由于最后Thread-0线程一直处于await没有其他线程去唤醒了,程序进程会一直阻塞中。

 

最后,看一下lock.newCondition()的说明:

Condition java.util.concurrent.locks.Lock.newCondition()

Returns a new Condition instance that is bound to this Lock instance.
Before waiting on the condition the lock must be held by thecurrent thread.
A call to Condition.await() will atomically release the lockbefore waiting
and re-acquire the lock before the wait returns.

newCondition()会返回一个与当前lock绑定的Condition实例。当前线程必须先获得lock,才能condition.await()。

一旦调用condition.await(),当前线程会释放lock然后进入waiting(此时lock会被其他线程获得),并且在从wait返回之前会重新申请锁(持有锁的线程signal通知其他wait线程重新申请锁,而后该持锁线程会释放锁)。

 

以上是关于java并发编程中的ReentrantLock的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程,深入理解ReentrantLock

Java Review - 并发编程_独占锁ReentrantLock原理&源码剖析

Java Review - 并发编程_独占锁ReentrantLock原理&源码剖析

Java并发编程:ReentrantLock-NonfairSync源码逐行深度分析(中)

Java并发编程15ReentrantLock实现原理深入探究

Java并发编程实战—–“J.U.C”:ReentrantLock之二lock方法分析