1、几种语句块的区别

  (1)fork……join:块内语句以并发方式执行

  (2)begin……end:块内语句以顺序方式执行

  (3)fork……join_none:其块内语句执行时,父线程继续执行

  (4)fork……join_any:其块内第一个语句完成后,父线程才继续执行,其他停顿的线程也得以继续

  在并发线程中务必使用自动变量来保存数值

2、停止线程

  (1)使用disable语句可以用于停止SV中的线程

  (2)使用disable fork语句能够停止从当前线程中衍生出来的所有子线程

3、线程间的通信

  (1)线程间数据的交换和控制的同步被称为线程间的通信(IPC),在SV中可以使用事件、旗语和信箱来完成。

  (2)边沿敏感的@操作符用来阻塞线程,->操作符用来触发线程,电平敏感的wait(e1.triggered())不会引起阻塞

  (3)传递事件:SV中的事件可以像参数一样传递给子程序

  (4)等待多个事件:wait fork 或者使用线程计数(例7.27-29)

4、旗语(semaphore)

  使用旗语可以实现对同一资源的访问控制。当测试平台中存在一个资源,如一条总线,对应着多个请求方,而实际的物理设计中又只允许单一驱动时,便可以使用旗语。在SV中,一个线程如果请求控制权而得不到,则会一直阻塞,多个阻塞的线程会以先进先出的方式进行排队。

  (1)旗语的三种基本操作:new方法可以创建一个带单个或多个钥匙的旗语,get可以获取一个或多个钥匙,put则可以返回一个或多个钥匙。如果试图获取一个旗语而希望不被阻塞,可以使用try_get()函数,它返回1表示有足够多的钥匙,返回0表示钥匙不够。

5、信箱(mailbox)

  (1)信箱可以看成是一个具有源端和收端的FIFO,源端把数据放进信箱,收端则从信箱中获取数据。当源端线程试图向一个容量固定并且已经饱和的信箱里放入数值时,会发生阻塞;当收端线程试图从一个空信箱里移走数据,也会发生阻塞。

  (2)信箱是一种对象,调用new函数来进行实例化,例化时有一个可选的参数size指定信箱的大小,缺省情况下容量不限。

  (3)信箱的基本操作

    put任务把数据放入信箱,get任务则可以移除数据。如果信箱为满,put会阻塞;如果信箱为空,get会阻塞.如果不希望在访问信箱时出现阻塞,可以使用try_get()和try_peek()函数,如果函数执行成功,它们返回非零值,否则返回0.

    get 是从邮箱中移出数据,peek(窥视)则探视信箱里的数据但是不把它移出

  (4)定容信箱在两个线程之间扮演了一个缓冲器的角色(例7.37)

  (5)实现线程同步的几种方式

    定容信箱加探视(peek):消费方使用peek()来探视信箱里的数据而不将其移出,当消费方处理完数据后,便使用get()移出数据。

    信箱加事件:在生产方把数据放入信箱后使用事件来阻塞它,等消费方处理完数据后再触发事件。

    使用两个信箱:一个信箱传递数据,另外一个信箱把消费方的完成信息发回给生产方。

    使用变量或旗语

6、结论

  设计可以用很多并发运行的独立块来建模,所以测试平台也必须能够产生很多激励流并检验并发线程的反应。所以这些都被组织在一个层次化的测试平台中,并在顶层环境里得到统一。SV在标准的fork……join之外,引入了诸如fork……join_none和fork……join_any这些用于动态创建线程的功能强大的结构。线程间可以使用事件、旗语、信箱,以及经典的@事件控制和wait语句来实现通信和同步。

7、程序示例

(1)事件

program test7;
event e1,e2;
initial begin
$display("@%0t:1:before triggered",$time);
->e1;
//wait(e2.triggered());
@(e2);
$display("@%0t:1:after triggered",$time);
end initial begin
$display("@%0t:2:before triggered",$time);
->e2;
//wait(e1.triggered());
@(e1);
$display("@%0t:2:after triggered",$time);
end endprogram:test7

输出:

# @::before triggered
# @::before triggered
# @::after triggered

(2)定容信箱

program test7_2;
//定容信箱
initial begin
mailbox mbx;
mbx = new(); //容量为1
$display("====== Constant volume mailbox =====");
fork
//生产方线程
for (int i=;i<;i++) begin
$display("Producer:before put (%0d)",i);
mbx.put(i);
//$display("Producer:after put (%0d)",i);
end
//消费者线程
repeat() begin
int j;
#1ns mbx.get(j);
$display("Consumer:after get (%0d)",j);
end
join end
endprogram

输出:

# ====== Constant volume mailbox =====
# Producer:before put ()
# Producer:before put ()
# Consumer:after get ()
# Producer:before put ()
# Consumer:after get ()
# Consumer:after get ()

(3)使用信箱和事件来实现线程的同步

program automatic mbx_evt;
mailbox mbx;
event handshake;
class Producer;
task run;
for (int i=;i<;i++) begin
$display("Producer:before put (%0d)",i);
mbx.put(i);
@handshake; //用事件阻塞
$display("Producer:after put (%0d)",i);
end
endtask
endclass class Consumer;
task run;
int i;
repeat () begin
mbx.get(i);
$display("Consumer:after get (%0d)",i);
->handshake; //取出数据之后触发事件
end
endtask
endclass Producer p;
Consumer c;
initial begin
mbx=new();
p=new();
c=new();
//使生产和消费并发运行
fork
p.run();
c.run();
join end endprogram

输出:

# Producer:before put ()
# Consumer:after get ()
# Producer:after put ()
# Producer:before put ()
# Consumer:after get ()
# Producer:after put ()
# Producer:before put ()
# Consumer:after get ()
# Producer:after put ()

07-SV线程以及线程间的通信的更多相关文章

  1. Python网络编程(进程池、进程间的通信)

    线程池的原理:        线程池是预先创建线程的一种技术.线程池在还没有任务到来之前,        创建一定数量的线程,放入空闲队列中.这些线程都是处于睡眠状态,        即均为启动,不消 ...

  2. iOS开发多线程篇—线程间的通信

    iOS开发多线程篇—线程间的通信 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任 ...

  3. Java核心知识点学习----多线程并发之线程间的通信,notify,wait

    1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...

  4. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  5. iOS边练边学--多线程NSOperation介绍,子类实现多线程的介绍(任务和队列),队列的取消、暂停(挂起)和恢复,操作依赖与线程间的通信

    一.NSOperation NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后将NSOperation对象添加 ...

  6. ZeroMQ(java)之I/O线程的实现与组件间的通信

    算是开始读ZeroMQ(java)的代码实现了吧,现在有了一个大体的了解,看起来实现是比较的干净的,抽象什么的不算复杂... 这里先来看看它的I/O线程的实现吧,顺带看看是如何实现组件的通信的.... ...

  7. iOS开发多线程篇—线程间的通信(转)

    这里转载 给自己一个备份 一.简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信 线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转 ...

  8. 新建线程与UI线程间的通信

    现在用一个实例来演示一下自己的新建线程与UI线程间的通信. UI界面包含3个控件: 一个输入框,用来输入数字: 一个显示框,用来显示从2开始,到输入数字之间的所有质数: 一个按钮,点击后获取输入框输入 ...

  9. C# 线程间互相通信

    C#线程间互相通信主要用到两个类:AutoResetEvent和ManualResetEvent. 一.AutoResetEvent AutoResetEvent 允许线程通过发信号互相通信,线程通过 ...

随机推荐

  1. gRPC in ASP.NET Core 3.x - gRPC 简介

    gRPC的结构 在我们搭建gRPC通信系统之前,首先需要知道gRPC的结构组成. 首先,需要一个server(服务器),它用来接收和处理请求,然后返回响应. 既然有server,那么肯定有client ...

  2. Day5前端学习之路——盒模型和浮动

    盒子模型 浮动float 一.盒子模型 (1)content内容区 width和height是框内容显示的区域——包括框内的文本内容,以及表示嵌套子元素的其他框,也可以使用min-width.max- ...

  3. 为什么我不建议在C#中用下划线_开头来表示私有字段

    我在C#官方文档的使用属性里看到这种代码: public class Date { private int _month = 7; // Backing store public int Month ...

  4. Blazor client-side Preview 预览版 如何调试 Debug

    首先我们使用最简单的模板案例,里面有一个Counter计数器,你可以在创建模板中找到. 首先需要设置运行调试方式为IIS Express.这意味着,MAC可能不能使用调试. 然后开启运行而不调试(Ct ...

  5. 使用Nginx对.NetCore站点进行反向代理

    前言 之前的博客我已经在Linux上部署好了.NetCore站点且通过Supervisor对站点进行了进程守护,同时也安装好了Nginx.Nginx的用处非常大,还是简单说下,它最大的功能就是方便我们 ...

  6. CSS中的圣杯布局与双飞翼布局

    一,圣杯布局 1,什么是圣杯布局? 所谓圣杯布局就是用于实现一个两侧宽度固定,中间宽度自适应的三栏布局 2,构建圣杯布局的步骤: 2.1,添加一个容器,在这个容器中添加放三个盒子(左.中.右): 2. ...

  7. java工作流系统表单自动 获取数据

    关键词:工作流快速开发平台  工作流流设计  业务流程管理   asp.net 开源工作流  bpm工作流系统  java工作流主流框架  自定义工作流引擎 表单设计器  流程设计器 什么是数据自动获 ...

  8. 【Android开发艺术探索】四大组件的工作过程

    个人博客 http://www.milovetingting.cn 四大组件的工作过程 四大组件:Activity.Service.BroadcastReceiver.ContentProvider ...

  9. windows快捷键记录

    -1: 装完iis, run -> inetmgr 弹出iis管理器 0.按住Shift键右击鼠标打开命令行窗口 1.ODBC数据源管理器run->odbcad32 2.计算机管理(查看设 ...

  10. 从零开始一个个人博客 by asp.net core and angular(一)

    这是一个个人叙述自己建设博客的帖子,既然是第一篇那肯定是不牵扯代码了,主要讲一下大体的东西,微软最新的web框架应该就数asp.net core 3.1了这是一个长期支持版,而且是跨平台又开源版本,所 ...