Lock实现线程间定制化通信

这篇具有很好参考价值的文章主要介绍了Lock实现线程间定制化通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Lock实现线程间定制化通信

案例

要求

三个线程,AA BB CC AA线程打印5次,BB线程打印10次,CC线程打印15次

代码实现
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
 * @author 长名06
 * @version 1.0
 * 线程定制化通信
 */
//第一步,创建共享资源,和操作方法
class ShareFlag {

    private Lock lock = new ReentrantLock();
    private int flag = 1;

    private Condition c1 = lock.newCondition();//一个Condition对象,只能唤醒由该对象阻塞的线程
    private Condition c2 = lock.newCondition();
    private Condition c3 = lock.newCondition();

    public void print5(int loop) throws InterruptedException {
        lock.lock();

        try {
            //第四步,避免虚假唤醒现象
            while (flag != 1) {//第2.1步 判断是否满足线程工作条件,阻塞
                c1.await();
            }
            //第2.2步 具体执行
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                        + "flag=" + flag + "轮数" + loop);
            }
            flag = 2;
            //通知(唤醒等待线程)
            c2.signal();
        } finally {
            lock.unlock();
        }

    }

    public void print10(int loop) throws InterruptedException {
        lock.lock();

        try {

            while (flag != 2) {
                c2.await();
            }

            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                        + "flag=" + flag + "轮数" + loop);
            }
            flag = 3;
            //通知(唤醒等待线程)
            c3.signal();
        } finally {
            lock.unlock();
        }

    }

    public void print15(int loop) throws InterruptedException {
        lock.lock();

        try {

            while (flag != 3) {
                c3.await();
            }

            for (int i = 0; i < 15; i++) {
                System.out.println(Thread.currentThread().getName() + "\t" + i +"次输出"
                        + "flag=" + flag + "轮数" + loop);
            }
            flag = 1;
            //通知(唤醒等待线程)
            c1.signal();
        } finally {
            lock.unlock();
        }

    }

}

public class ThreadDemoByCust {
    public static void main(String[] args) {
        ShareFlag shareFlag = new ShareFlag();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    shareFlag.print5(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "AA").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    shareFlag.print10(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "BB").start();

        new Thread(() -> {
            for (int i = 1; i <= 10; i++) {
                try {
                    shareFlag.print15(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "CC").start();
    }
}
学习时,关于代码的疑问

不理解,为什么一定是,AA线程执行完后,,BB线程执行完后,是c3是c2去执行唤醒一个等待线程操作去执行唤醒一个等待线程的操作,CC线程执行完后,是c1执行唤醒一个等待线程的操作。先往后面看,后续回来解答这个问题。

解答

是为了满足要求中的顺序,最开始三个AA,BB,CC线程,并行执行,因为flag初始值是1,所以AA先执行第一次循环,执行print5,然后循环输出5次后,flag = 2了(AA被c1阻塞),为了保证要求,再BB输出10次,则需要使用c2去唤醒BB线程,为什么是c2,因为BB线程在,最开始flag = 1时,是由c2去阻塞的,这里如果是c3对象阻塞的,则必须要用c3对象唤醒,因为Condition对象,只能唤醒由该对象阻塞的线程。后面BB线程切换CC线程,CC线程切换AA线程也是同理。

只是为了记录自己的学习历程,且本人水平有限,不对之处,请指正。文章来源地址https://www.toymoban.com/news/detail-719955.html

到了这里,关于Lock实现线程间定制化通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 线程间互斥-mutex互斥锁和lock_guard

    锁+双重判断的技法 竟态条件:多线程程序执行的结果一致,不会随着CPU对线程不同的调用顺序 线程不安全的代码如下 输出的部分结果里有很多重复的数字,相当于同一张票被卖出多次,原因在于 ticketCount–; 是线程不安全的,理由如下 某一时刻ticketCount = 99,thread1此时调用

    2024年02月03日
    浏览(37)
  • 线程间实现通信的几种方式

    线程间通信的模型有两种:共享内存和消息传递,下面介绍的都是围绕这两个来实现 有两个线程A和B,B线程向一个集合里面依次添加元素“abc”字符串,一共添加10次,当添加到第五次的时候,希望线程A能够收到线程B的通知,然后B线程执行相关的业务操作 Object类提供了线程

    2024年02月15日
    浏览(66)
  • 【C#】知识点实践序列之Lock的输出多线程信息

    大家好,我是全栈小5,欢迎来到《小5讲堂之知识点实践序列》文章。 2024年第2篇文章,此篇文章是C#知识点实践序列之Lock知识点,博主能力有限,理解水平有限,若有不对之处望指正! 本篇在Lock锁定代码块输出多线程信息,用于判断是否是同一个线程还是不同线程。 上篇

    2024年02月03日
    浏览(47)
  • 【JavaSE专栏80】多线程通信,多个线程之间如何实现信息传递和同步?

    作者主页 :Designer 小郑 作者简介 :3年JAVA全栈开发经验,专注JAVA技术、系统定制、远程指导,致力于企业数字化转型,CSDN学院、蓝桥云课认证讲师。 主打方向 :Vue、SpringBoot、微信小程序 本文讲解了 Java 中多线程通信的语法和应用场景,并给出了样例代码。多线程通信是

    2024年02月11日
    浏览(44)
  • 有关多线程环境下的Volatile、lock、Interlocked和Synchronized们

    📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香! 📢本文作者:由webmote 原创 📢作者格言:新的征程,我们面对的不仅仅是技术还有人心,人心不可测,海水不可量,唯有技术,才是深沉黑夜中的一座闪烁的灯塔 ! 多线程下的变量访问,就如同

    2024年02月08日
    浏览(37)
  • 【Linux后端服务器开发】封装线程池实现TCP多线程通信

    目录 一、线程池模块 Thread.h LockGuard.h ThreadPool.h 二、任务模块模块 Task.h 三、日志模块 Log.h 四、守护进程模块 Deamon.h  五、TCP通信模块 Server.h Client.h server.cpp client.cpp 关于TCP通信协议的封装,此篇博客有详述: 【Linux后端服务器开发】TCP通信设计_命运on-9的博客-CSDN博客 线程池

    2024年02月16日
    浏览(44)
  • C++11并发与多线程笔记(6) unique_lock(类模板)

    unique_lock 是一个类模板。 unique_lock 比 lock_guard 灵活很多 ( 多出来很多用法 ),效率差一点,内存占用多一些。 使用: unique_lockmutex myUniLock(myMutex); std::adopt_lock:标记作用,表示这个互斥量已经被lock()(方便记忆:已经被lock()收养了,不需要再次lock() ),即 不需要在构造函

    2024年02月12日
    浏览(42)
  • 多线程基础(三)JUC并发包:Lock锁、CountDownLath、CyclicBarrier、Semaphore、LockSupport

    我们可以使用 ReentrantLock 来替代 Synchronized锁,实现方法为: 使用Synchronized是自动解锁的。但是使用lock锁,必须使用try-catch-finally包裹,在try中加锁,在finally中释放锁。 允许同一时刻多个读线程访问,但所有写线程均被阻塞。读写分离,并发性提升。 java中实现类的读写锁为

    2024年02月06日
    浏览(37)
  • 利用线程池多线程并发实现TCP两端通信交互,并将服务端设为守护进程

    利用线程池多线程并发实现基于TCP通信的多个客户端与服务端之间的交互,客户端发送数据,服务端接收后处理数据并返回。服务端为守护进程 封装一个记录日志的类,将程序运行的信息保存到文件 封装线程类、服务端处理任务类以及将锁进行封装,为方便实现线程池 实现

    2024年02月14日
    浏览(40)
  • 从汇编角度解释线程间互斥-mutex互斥锁与lock_guard的使用

    我们创建三个线程同时进行购票,代码如下  我们再看这段代码的汇编过程  汇编代码如下: 上述汇编过程的解读为: 将ticketCount的值从内存放到寄存器eax 通过寄存器完成减法操作 将运算结果再从eax寄存器中放到内存中 可以看到,三个线程在执行代码时,每个线程在执行到

    2024年02月19日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包