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. ubuntu docker中crontab任务不执行的问题

    problem of task of crontab in docker of ubuntu do not working! 由于各种原因,要在Ubuntu docker上部署crontab任务,如 ...

  2. LeetCode 126. Word Ladder II 单词接龙 II(C++/Java)

    题目: Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transfo ...

  3. 编写 Django 应用单元测试

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 我们博客功能越来越来完善了,但这也带来了一个问题,我们不敢轻易地修改已有功能的代码了 ...

  4. Rust入坑指南:步步为营

    俗话说:"测试写得好,奖金少不了." 有经验的开发人员通常会通过单元测试来保证代码基本逻辑的正确性.如果你是一名新手开发者,并且还没体会到单元测试的好处,那么建议你先读一下我之前的 ...

  5. WLAN802.11

    IEEE 802.11,1997年,原始标准(2Mbit/s,播在2.4GHz).DSSS, FHSS.该协议的一大缺点是它提供了太多的选择使得互操作性很难实现.所以它不严密,更像是一个beta标准, ...

  6. H3C router cmd

    LAN转WAN:接口下port link-mode route windows CMD,本地连接5的链路本地地址经常有一个百分号加一个数字,该数字即接口索引,fe80::8c79:e4f9:f5a3: ...

  7. IP unnumbered interface,某个接口不编号,某个接口不分配IP地址

    OSPFv2中,提到点到点链路可以是unnumbered,不编号,不分配IP地址 12.4.1.1.  Describing point-to-point interfaces             ...

  8. centos 7 设置 本地更新源

    #yum-config-manager --disable \*--屏弊所有更新源#mkdir /r7iso# cd /run/media/{用户名}/CentOS\ 7\ x86_64/ #cp - ...

  9. JVM源码分析之临门一脚的OutOfMemoryError完全解读

    概述 OutOfMemoryError,说的是java.lang.OutOfMemoryError,是JDK里自带的异常,顾名思义,说的就是内存溢出,当我们的系统内存严重不足的时候就会抛出这个异常(P ...

  10. Python常用库 - os库

    os简单介绍 os 模块提供了非常丰富的方法用来处理文件和目录 os关于目录路径的方法 # 获取当前路径 path = os.getcwd() # 获取当前绝对路径 os.path.abspath(p ...