线程之间的通信(事件event、信箱mailbox、旗语semaphore)

2024-03-27 01:10

本文主要是介绍线程之间的通信(事件event、信箱mailbox、旗语semaphore),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

看到一篇好博客,转载下https://blog.csdn.net/qq_41337361/article/details/122723681?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-122723681-blog-113836405.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-4-122723681-blog-113836405.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=8

目录

0.前言

1.事件event

2.信箱mailbox

3.旗语semaphore


0.前言

若多个线程之间想要进行数据交换或者知道彼此的状态以决定执行什么线程,SV中通过event、mailbox、semaphore来进行线程通信。其中event是2个线程之间的通信,semaphore是≥2个线程之间的通信。

1.事件event

当我们需要一个进程在另一个进程触发事件的时候运行该怎么办?SV中引入了event来解决这个问题。其语法如下:

触发:-> (非阻塞)(类比于接电话)

等待:@ or wait(阻塞)(类比于打电话)

注意:若用->和@搭配,一定要先@再->;若用->和wait搭配,则谁先谁后都可以。

为什么@和wait会有这种差别呢?因为@是等待边沿触发,而非1触发,因此必须先等,知道信号发生跳变,如果信号已经发生跳变了,@是察觉不到的;而wait是电平1触发,因此自然而然的弥补了@的缺点,因此也不用有先后顺序

->和@搭配:

  1. program automatic test();
  2. event e1,e2;
  3. initial begin
  4. $display("@%0d:1:before trigger",$time);
  5. ->e1;//->和@搭配,先->不行,非阻塞,去下一个
  6. @e2;//等待e2被触发,阻塞,下面的不执行
  7. $display("@%0d:1:after trigger",$time);
  8. end
  9. initial begin
  10. $display("@%0d:2:before trigger",$time);
  11. -> e2;//上面的等到了e2,此时上面的display运行
  12. @e1;//阻塞,顺序错误,下面的display不会执行
  13. $display("@%0d:2:after trigger",$time);
  14. end
  15. endprogram
  16. /* 仿真结果
  17. @0:1:before trigger
  18. @0:2:before trigger
  19. @0:1:after trigger */

->和wait搭配 :

  1. program automatic test();
  2. event e1,e2;
  3. initial begin
  4. $display("@%0d:1:before trigger",$time); //1
  5. -> e1;//触发1
  6. wait(e2.triggered);//阻塞,等待e2被触发
  7. $display("@%0d:1:after trigger",$time);//4
  8. end
  9. initial begin//顺序执行完后,再回到上面执行wait后的display
  10. $display("@%0d:2:before trigger",$time); //2
  11. -> e2;//e2被触发
  12. wait(e1.triggered);//e1已经被触发
  13. $display("@%0d:2:after trigger",$time);//3
  14. end
  15. endprogram
  16. /*仿真结果:
  17. @0:1:before trigger
  18. @0:2:before trigger
  19. @0:2:after trigger
  20. @0:1:after trigge */

wait_order:

wait_order阻塞等待多个事件的触发,并且要求这多个事件按照用户决定顺序触发。wait_order可以和else一同使用,当多个事件 按顺序触发时,执行wait_order后的语句,否则执行else后的语句。 

  1. module tb;
  2. event a, b, c;
  3. initial begin
  4. #10 -> a;
  5. #10 -> b;
  6. #10 -> c;
  7. end
  8. initial begin
  9. wait_order (a,b,c)
  10. $display ("Events were executed in the correct order");
  11. else
  12. $display ("Events were NOT executed in the correct order !");
  13. end
  14. endmodule

2.信箱mailbox

mailbox是一种在进程之间交换消息的机制。数据可以通过一个进程发送到Mailbox, 然后由另一个进程获取。数据可以是任何有效的SystemVerilog数据类型,包括类 class数据类型。

比如在一个验证环境中,generator将激励给driver,往往不是直接发送给driver,而是发送给generator和driver直接的mailbox,driver获取数据的时候,从mailbox中直接获得。

mailbox有几种SV自带函数,如下所示:

new()是对mailbox进行实例化;

put(xxx)是将数据放入mailbox中,是阻塞的,若mailbox放满,放不进去,则会一直重复放的动作,程序被阻塞到这个语句;

try_put(xxx)功能与put一样,但其是非阻塞的,放一次,放不进去就不放了;

get(xxx)是从mailbox中取数据,也是阻塞语句;

peek(xxx)和get()功能一致,但是get()从mailbox取出数据后,mailbox的数据就没了,而peek相当于复制了一份出来;num()是用来计算mailbox中有几个数据的。

关于mailbox的具体应用可参考这篇文章:SV小项目—异步fifo的简单验证环境搭建。

下面看代码进一步理解mailbox的运用:

  1. //============事务============
  2. class transaction;
  3. rand bit valid;
  4. rand bit [7:0] data;
  5. endclass
  6. //=================generator================
  7. class generator;
  8. mailbox #(transaction) gen2drv;//声明mailbox句柄,并且指明该mailbox中只能存放transaction类型的数据
  9. transaction tr;
  10. function new (input mailbox #(transaction) gen2drv);//声明和外界通信的组件时,一定要new
  11. this.gen2drv=gen2drv;
  12. endfunction
  13. task gen(input int num);//产生多少笔激励
  14. for(int i=0;i<num;i++) begin
  15. tr=new();
  16. assert(tr.randomize)
  17. gen2drv.put(tr);//把产生的一笔激励放入mailbox中
  18. $display(“trans valid =%d”,tr.valid);
  19. $display(“trans data =%d”,tr.data);
  20. #1ns;
  21. end
  22. endtask
  23. endclass
  24. //=====================驱动========================
  25. class driver;
  26. mailbox #(transaction) gen2drv;
  27. transaction tr;
  28. function new (input mailbox #(transaction) gen2drv);
  29. this.gen2drv=gen2drv;
  30. endfunction
  31. task run;
  32. tr=new();
  33. while(1) begin
  34. gen2drv.get(tr);//从mailbox中取出数据
  35. $display(“trans valid =%d”,tr.valid);
  36. $display(“trans data =%d”,tr.data);
  37. end
  38. endtask
  39. endclass
  40. //==================test文件==================
  41. program test;
  42. mailbox #(transaction) gen2drv;
  43. driver drv;
  44. generator gen;
  45. initial begin
  46. gen2drv=new();
  47. drv=new(gen2drv);
  48. gen=new(gen2drv);
  49. fork
  50. gen.gen(5);
  51. drv.run;
  52. join_any
  53. end
  54. endprogram

3.旗语semaphore

当多个线程访问同一资源的时候,而这个资源只允许一个线程访问的时候,就可以用旗语来进行控制;如果把资源比作为一个仓库的话,旗语就相当于一把钥匙,每个线程需要拿到钥匙后才能对资源进行访问。当然也可以有多把钥匙,对应同一资源可以同时被访问的最大数量。

旗语有如下几个操作函数:

new(); //对“钥匙”进行实例化

get(); //线程获取钥匙,阻塞

put(); //线程将钥匙放回,阻塞

try_get(); //非阻塞

  1. class bridge;
  2. semaphore key;//声明一个旗语钥匙
  3. function new ();
  4. this.key=new(1);//实例化1把钥匙
  5. endfunction
  6. task go_on(string name);
  7. $display(“@%0t: %s wants to go trough the brdige”,$time,name);
  8. key.get();//拿到钥匙
  9. #1ns;
  10. $display(“@%0t: %s gets permission to go trough the brdige”,$time,name);
  11. #10ns;
  12. endtask
  13. task go_off(string name);
  14. $display(“@%0t: %s goes off the brdige”,$time,name);
  15. key.put();//放回钥匙
  16. #1ns;
  17. $display(“@%0t: %s returned the key.”,$time,name);
  18. endtask
  19. endclass
  20. program test;
  21. bridge brg;
  22. string name1=”Alex”;
  23. string name2=”Bob”;
  24. string name3=”Calvin”;
  25. string name4=”Denise”;
  26. initial begin
  27. brg=new();
  28. fork
  29. begin
  30. brg.go_on(name1);
  31. brg.go_off(name1);
  32. end
  33. begin
  34. brg.go_on(name2);
  35. brg.go_off(name2);
  36. end
  37. begin
  38. brg.go_on(name3);
  39. brg.go_off(name3);
  40. end
  41. begin
  42. brg.go_on(name4);
  43. brg.go_off(name4);
  44. end
  45. join
  46. end
  47. endprogram

仿真结果如下:

可见若多个线程同时要拿钥匙,则按照先后顺序依次来;下一线程只有等到上一线程归还钥匙后才能拿到钥匙。 


http://www.taodudu.cc/news/show-8507319.html

相关文章:

  • vs2019新建Qt工程中双击 .ui 文件无法打开
  • createjs实现贪吃蛇,包含成长及游戏条件重置
  • 删除、创建、验证Kafka安装自带的__consumer_offsets topic
  • Java代码基础算法练习-报数问题-2024.03.26
  • Flutter 项目架构技术指南
  • LeetCode # 1372. 二叉树中的最长交错路径
  • linux ipc消息的权限,linux 下进程编程-System V IPC,消息队列,共享内存,旗语
  • systemverilog中线程间通信方法---事件event/旗语somaphore/信箱mailbox
  • SV-线程同步与通信-事件-旗语-信箱
  • Systemverilog线程之间的通信:事件【event】,旗语以及可执行代码
  • linux旗语
  • Semaphore旗语
  • Linux旗语编程实例
  • SystemVerilog进程间通信——旗语Semaphore/信箱Mailbox
  • 旗语(SEM)同步
  • SV中关于多线程同步的理解
  • 【2024美赛】F题(中英文):减少非法野生动物贸易Problem F: Reducing Illegal Wildlife Trade
  • 区块链如何改变世界贸易
  • 对外贸易经济大学计算机考研,对外经济贸易大学考研难吗?一般要什么水平才可以进入?...
  • 2022年自考专业考试(英语)国际贸易实务(一)练习题
  • 有一件事我想了很久了却一直没有做
  • 今天终于了却心头一块大事
  • pagehelper分页查询的一个坑,明明下一页没有数据了却还是返回了数据
  • js函数明明定义了却报未定义错误
  • kitti2bag包pip install pykitti明明安装了却显示没有
  • Maven导入依赖时爆红/导入依赖了却没用
  • ax2.set_xlim 不起作用,调整了却没有任何的作用
  • git远端分支建好了却无法获取远端分支
  • Pillow安装了却提示没有安装
  • el-form明明输入值了却一直报错
  • 链表面试题(动图详解)-明明做出来了却为什么没有Offer?
  • 全屏了却判断为未全屏(已解决)
  • 已经做烂了却还是不会做?
  • pagehelper分页查询明明下一页没有数据了却还是返回了数据
  • 踩雷之安装VMware Tools明明成功了却不生效
  • Tensorflow的gpu无法使用,明明安装了却用不了
  • 这篇关于线程之间的通信(事件event、信箱mailbox、旗语semaphore)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



    http://www.chinasem.cn/article/850466

    相关文章

    java Long 与long之间的转换流程

    《javaLong与long之间的转换流程》Long类提供了一些方法,用于在long和其他数据类型(如String)之间进行转换,本文将详细介绍如何在Java中实现Long和long之间的转换,感... 目录概述流程步骤1:将long转换为Long对象步骤2:将Longhttp://www.cppcns.c

    Java中实现线程的创建和启动的方法

    《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

    Linux实现线程同步的多种方式汇总

    《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流

    Java中常见队列举例详解(非线程安全)

    《Java中常见队列举例详解(非线程安全)》队列用于模拟队列这种数据结构,队列通常是指先进先出的容器,:本文主要介绍Java中常见队列(非线程安全)的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一.队列定义 二.常见接口 三.常见实现类3.1 ArrayDeque3.1.1 实现原理3.1.2

    SpringBoot3中使用虚拟线程的完整步骤

    《SpringBoot3中使用虚拟线程的完整步骤》在SpringBoot3中使用Java21+的虚拟线程(VirtualThreads)可以显著提升I/O密集型应用的并发能力,这篇文章为大家介绍了详细... 目录1. 环境准备2. 配置虚拟线程方式一:全局启用虚拟线程(Tomcat/Jetty)方式二:异步

    如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

    《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

    RabbitMQ工作模式中的RPC通信模式详解

    《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

    在Spring Boot中实现HTTPS加密通信及常见问题排查

    《在SpringBoot中实现HTTPS加密通信及常见问题排查》HTTPS是HTTP的安全版本,通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护,下面通过本文给大家介绍在SpringB... 目录一、HTTPS核心原理1.加密流程概述2.加密技术组合二、证书体系详解1、证书类型对比2. 证书获

    Python模拟串口通信的示例详解

    《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5

    基于C#实现MQTT通信实战

    《基于C#实现MQTT通信实战》MQTT消息队列遥测传输,在物联网领域应用的很广泛,它是基于Publish/Subscribe模式,具有简单易用,支持QoS,传输效率高的特点,下面我们就来看看C#实现... 目录1、连接主机2、订阅消息3、发布消息MQTT(Message Queueing Telemetr