线程之间的通信(事件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

    相关文章

    禁止平板,iPad长按弹出默认菜单事件

    通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

    day-51 合并零之间的节点

    思路 直接遍历链表即可,遇到val=0跳过,val非零则加在一起,最后返回即可 解题过程 返回链表可以有头结点,方便插入,返回head.next Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*

    系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

    本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

    【STM32】SPI通信-软件与硬件读写SPI

    SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

    【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

    【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

    vue2 组件通信

    props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

    线程的四种操作

    所属专栏:Java学习        1. 线程的开启 start和run的区别: run:描述了线程要执行的任务,也可以称为线程的入口 start:调用系统函数,真正的在系统内核中创建线程(创建PCB,加入到链表中),此处的start会根据不同的系统,分别调用不同的api,创建好之后的线程,再单独去执行run(所以说,start的本质是调用系统api,系统的api

    FreeRTOS内部机制学习03(事件组内部机制)

    文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

    linux中使用rust语言在不同进程之间通信

    第一种:使用mmap映射相同文件 fn main() {let pid = std::process::id();println!(

    java线程深度解析(六)——线程池技术

    http://blog.csdn.net/Daybreak1209/article/details/51382604 一种最为简单的线程创建和回收的方法: [html]  view plain copy new Thread(new Runnable(){                @Override               public voi