JUC学习------Lock实现线程之间的通信

文章预览

前言

前面已经了解了Synchronized实现线程之间的通信,使用关键字synchronizedwait()方法和notify()方式结合实现线程间通信,也就是等待/通知模式。在ReentrantLock中,是借助Condition对象进行实现的。下面对Lock实现线程之间的通信进行分析
Condition的创建方式如下:

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

Condition按字面意思理解就是条件,当然,我们也可以将其认为是条件进行使用,这样的话我们可以通过上述的代码创建多个Condition条件,我们就可以根据不同的条件来控制现成的等待和通知。而我们还知道,在使用关键字synchronizedwait()方法和notify()方式结合实现线程间通信的时候,notify/notifyAll的通知等待的线程时是随机的,显然使用Condition相对灵活很多,可以实现”选择性通知”。

这是因为,synchronized关键字相当于整个Lock对象只有一个单一Condition对象,所有的线程都注册到这个对象上。线程开始notifAll的时候,需要通知所有等待的线程,让他们开始竞争获得锁对象,没有选择权,这种方式相对于Condition条件的方式在效率上肯定Condition较高一些。

案例

实现多线程进行加一和减一的操作,当数字为1,进行减1,当数字为0,进行加1
主要方法对比如下:
(1)Objectwait()方法相当于Condition类中的await()方法;
(2)Objectnotify()方法相当于Condition类中的signal()方法;
(3)ObjectnotifyAll()方法相当于Condition类中的signalAll()方法;

首先,使用Lock的时候都需要先获取锁。

示例代码如下:

package com.juc;

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

/**
 * @author niuben
 */
//第一步,创建资源类
class LShare{
    private int number = 0;

    //创建Lock
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    //+1
    public void incr() throws InterruptedException {
        //上锁
        lock.lock();
        try{
            //判断
            while(number != 0){
                condition.await();
            }
            //干活
            number++;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            //通知其它线程
            condition.signalAll();
        }finally {
            //解锁
            lock.unlock();
        }
    }
    //-1
    public void decr() throws InterruptedException {
        //上锁
        lock.lock();
        try{
            //判断
            while(number != 1){
                condition.await();
            }
            //干活
            number--;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            //通知其它线程
            condition.signalAll();
        }finally {
            //解锁
            lock.unlock();
        }
    }
}
public class LockDemo1 {
    public static void main(String[] args) {
        LShare share = new LShare();

        new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"加加1").start();

        new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"减减1").start();

        new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                try {
                    share.incr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"加加2").start();

        new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                try {
                    share.decr();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"减减2").start();

    }
}

运行效果
在这里插入图片描述

注意

为防止虚假唤醒,代码中的判断最好换成while语句,
虚假唤醒可以参考一下,这篇博客https://blog.csdn.net/qq_39455116/article/details/87101633

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韭菜盖饭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值