ReentrantLock显示锁

前言:

synchronized和ReentrantLock同为锁机制,synchronized内置锁为同步锁的首选。而显示锁ReentrantLock,它并不是用来替代synchronized的,而是作为内置锁不适用时另一种可选择的高级功能。 


什么情况下使用ReentrantLock,这里不列详细的原理,只列比较容易理解的地方:

1、竞争资源激烈时用ReentrantLock,反之用synchronized;
  • 竞争资源不激烈的情况下,synchronized的性能较高,synchronized机制属于轻量级,对于只有少数线程中运行成本较低,而ReentrantLock相反。
  • 竞争资源激烈的情况下,ReentrantLock的性能较高,因为synchronized属于线程独占锁,比如A已经获得了该锁,B也想获得该锁就只有依靠阻塞来等待,直到A成功释放掉该锁(容易出现死锁),此时还有个操作就是CPU不断的在A和B之间切换,一旦还有CDEF等等若干个线程和B同一种情况,可想而知CPU在上下文切换上会浪费很多精力。而ReentrantLock锁的方式可以很好的优化这一问题。它的工作机制是如果A被锁住,BCDEF等线程试图获取该锁,一段时间后发现获取不到,它们可以中断自己,之后CPU不会再切换到这些线程而是专心去执行A的任务。所以在竞争激烈的情况下ReentrantLock更加有优势。(简单说就是JVM花更少的时间来调度,更多的时间来执行)
2、需要手动控制线程的中断、唤起等操作。
     因为ReentrantLock为显示锁,即可调用lock()/unlock()等方法进行操作,虽跟synchronized内建型锁相比代码缺乏优雅性,但和Condition相互配合操作性更加灵活。 


下面一个简单的Demo。
逻辑是实现一个简单的生产者和消费者模式的例子:
提一个简单的问题,让我们带着问题参考代码。
PS:这里为了代码的简介(懒),就拿Int型对象mQueue代替队列对象,请把mQueue想象成队列对象。。 

启动程序
public static void main(String[] args) {
    TestReentrantLock testReentrantLock = new TestReentrantLock();
    testReentrantLock.startTest();
}

下面为TestReentrantLock.java代码
public class TestReentrantLock {

    ReentrantLock reentrantLock = new ReentrantLock();
    Condition condition = reentrantLock.newCondition();
    int mQueue = 0;

    public void startTest() {
        newThread();
        producer();
    }

    public void newThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                consumer();
            }
        }).start();
    }

    public void consumer() {
        reentrantLock.lock();
        if (reentrantLock.isLocked()){
            System.out.println("\nConsumer gets the lock\n");
        }
        try {
            while (mQueue == 0) {
                System.out.println("The thread is waiting for consumers.\n");
                condition.await();
                System.out.println("The thread is starting for consumers.\n");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
            if (!reentrantLock.isLocked()){
                System.out.println("Consumer releases the lock\n");
            }
        }
        System.out.println("Done");
    }

    public void producer() {
        try {
            Thread.sleep(1000);
            reentrantLock.lock();
            Thread.sleep(5000);
            mQueue++;
            System.out.println("Producer add content\n");
            condition.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
            if (!reentrantLock.isLocked()){
                System.out.println("Producer releases the lock\n");
            }
        }
    }
}

1、创建一个线程,用ReentrantLock对象锁住,获取mQueue队列中的内容,如果有内容完成操作,如果没有内容则利用Condition对象中断线程,当Condition对象调用await()方法后会调用native方法自动解锁。
2、在新线程获取内容为空之后,主线程的producer()方法才执行,用ReentrantLock对象锁住,给mQueue添加内容,利用Condition对象调用signal()方法唤起新线程。
3、被唤起被中断的新线程,从被中断的代码继续向下执行,如果符合while()条件里面则重复执行其中的代码,不符合条件则跳出while()向下执行。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: synchronized和reentrantlock都是Java中用于实现线程同步的机制。 synchronized是Java中最基本的同步机制,它可以用于方法或代码块级别的同步。当一个线程进入synchronized代码块时,它会尝试获取,如果已经被其他线程持有,则该线程会被阻塞,直到被释放。synchronized机制是Java中最常用的同步机制之一,但它有一些限制,例如无法中断正在等待的线程,也无法尝试获取而不阻塞。 reentrantlock是Java中另一种同步机制,它提供了更多的灵活性和控制。与synchronized不同,reentrantlock可以中断正在等待的线程,也可以尝试获取而不阻塞。此外,reentrantlock还提供了一些高级功能,例如公平和可重入。但是,reentrantlock的使用比synchronized更复杂,需要手动获取和释放,并且需要注意避免死等问题。 总的来说,synchronized是Java中最基本的同步机制,适用于大多数情况。而reentrantlock则提供了更多的灵活性和控制,适用于一些特殊的场景。 ### 回答2: synchronized和ReentrantLock是Java中用于实现线程同步的两种机制。 synchronized是Java中最基本的线程同步机制,它使用了内置的监视器(也称为对象或互斥)来控制线程的访问。synchronized关键字可以用于方法或代码块,并且是隐式。当线程执行到synchronized关键字时,会自动获取,执行完后会自动释放synchronized关键字确保了在同一时间只有一个线程可以访问被定的代码或方法,从而保证了线程的安全性。然而,synchronized关键字也有一些缺点,比如无法获得时会一直阻塞等待和释放。 ReentrantLock是Java中的另一种线程同步机制,它是通过显示来实现的。ReentrantLock提供了更灵活的定操作,相比于synchronized,它具有更多的特性。ReentrantLock可以使用lock()和unlock()方法来手动加和解,这意味着我们可以更加精确地控制代码的同步性。ReentrantLock还支持可重入性,即线程可以多次获得同一个,提供了更高的灵活性。它还支持公平和非公平两种模式,可以按照先进先出的规则来选择获取的线程。此外,ReentrantLock还提供了一些高级功能,比如可中断、超时和条件变量等。 总的来说,synchronized是Java中最基本的线程同步机制,使用简单但灵活性较低。而ReentrantLock则提供了更多的功能和灵活性,但使用相对复杂一些。在实际应用中,我们可以根据具体需求来选择使用哪种线程同步机制。 ### 回答3: synchronized和ReentrantLock都是Java中用于实现线程同步的工具。 synchronized是Java中最常见的同步关键字,它可以应用在方法或代码块上。当一个线程获取到对象的synchronized时,其他线程就无法同时访问这个对象。当该线程执行完代码块或者方法,会释放,其他线程才能获得并执行。synchronized是隐式获取和释放的过程,非常方便,但也存在一些限制,例如无法中断一个正在等待获取的线程。 ReentrantLock是Java中提供的一种显示,可以实现与synchronized类似的功能。与synchronized不同的是,ReentrantLock提供了更灵活和更强大的功能。它允许更细粒度的控制定的获取和释放,例如通过lock()和unlock()方法手动获取和释放,也可以通过tryLock()方法尝试获取而不需要一直等待。此外,ReentrantLock还支持公平性,即按照线程请求的顺序获取,避免产生线程饥饿现象。而synchronized则不保证公平性。 另外,ReentrantLock提供了Condition接口,可以使用newCondition()方法创建多个条件变量。条件变量可以用于线程间的通信,可以让某个线程等待特定条件满足后再继续执行,或者通知其他等待线程某个条件已经满足。 总的来说,synchronized是Java中隐式机制的实现,使用方便但功能有限;而ReentrantLock显示机制的实现,提供了更多灵活和强大的功能,但使用起来需要更细致的控制。根据具体情况需要,我们可以选择合适的同步机制来保证线程安全。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值