资讯详情

线程的同步

在许多情况下,通过邮箱连接的两个线程应该是一致的,这样生产者就不会跑到消费者面前。该方法的优点是,它可以使生成激励的整个链在运行过程中保持一致。最高级别的发生器需要等到底部的最后一件事才能结束。

如果生产者和消费者的步骤相同,则需要额外的握手信号。如下所示,生产者和消费者是两类,使用邮箱交换整数,但两者之间没有明显的同步信号。直到生产者结束,消费者才开始。

program automatic unsynchronized;     mailbox mbx;     class Producer;         task run();             for (int i=1;i<4;i  ) begin                 $display("Producer:before put( )",i);                 mbx.put(i);             end         endtask     endclass      class Consumer;         task run();             int i;             repeat (3) begin                 mbx.get(i);                 $display("Consumer:after get( )",i);             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(1) Producer: before put(2) Producer: before put(3) Consumer: after get(1) Consumer: after get(2) Consumer: after get(3)

它会导致先完全放入后取出的情况,而不是同步。为此,介绍了消费者和生产者同步操作的三种方法。

使用定容信箱和peek

program automatic synch_peek;     mailbox mbx;     class Consumer;         task run();             int i;             repeat(3) begin                 mbx.peek(i);                 $display("Consumer:after get( )",i);                 mbx.get(i);             end         endtask     endclass  Producer p; Consumer c; initial begin     mbx=new(1);     p=new();     c=new();     fork         p.run();         c.run();     join     end endprogram

若消费者使用get()替代peek()启动循环,然后事物会立即从邮箱中移出,这样生产者就可以在消费者完成事物处理之前生成新的数据。虽然可以看出,生产者和消费者的步伐是一致的,但生产者仍然比消费者提前一件事,因为容量为1的固定容器只有在你对第二件事进行put堵塞发生在操作过程中。

Producer:before put(1) Producer:before put(2) Consumer:after get(1) Consumer:after get(2) Producer:before put(3) Consumer:after get(3)

使用信箱事件完成线程同步

你想让两个线程使用握手信号,这样制造商就不会超过消费者。由于消费者等待制造商以阻塞的方式使用邮箱,制造商也可以阻塞等待消费方式完成邮箱条目的处理。

program automatic mbx_evt; mailbox mbx; event handshake;     class Producer;         task run;             for(int i=1;i<4;i  ) begin                 $display("Producer:before put( )",i);                 mbx.put(i);                 @handshake;                 $display("Producer:after put( )",i);             end         endtask     endclass      class Consumer;         task run;             int i;             repeat(3) begin                 mbx.get(i);                 $display("Consumer:after get( )",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

这样,生产者和消费者在运行过程中成功同步,因为生产者在阅读旧值之前不会产生新值。

使用两个信箱同步线程

program automatic mbx_evt; mailbox mbx,rtn;     class Producer;         task run;             int k;             for(int i=1;i<4;i  ) begin                 $display("Producer:before put( )",i);                 mbx.put(i);                 rtn.get(k);    //@handshake;                 $display("Producer:after put( )",i);             end         endtask     endclass      class Consumer;         task run;             int i;             repeat(3) begin                 $display("Consumer:before get");                 mbx.get(i);                 $display("Consumer:after get( )",i);                 rtn.put(-i);             end         endtask     endclass      Producer p;     Consumer c;     initial begin         mbx=new();         p=new();         c=new();         fork             p.run();             c.run();         join     end endprogram

事实上,它类似于使用事件模式,但信箱可以在这里传递信息rtn信箱中的信息只是原始整数的相反值,便于调试。

其它同步技术

握手也可以通过变量或旗语阻塞线程。事件是最简单的结构,其次是变量。旗语相当于第二个邮箱,但没有信息交换。SV的定容信箱技术较差,原因是无法在生产方放入第一个事务的时候让它阻塞,生产方一直比消费方提前一个事务的时间。

标签: mbx连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

 锐单商城 - 一站式电子元器件采购平台  

 深圳锐单电子有限公司