本文章仅为作者自学心得,为便于加深记忆和输出自己的理解,也为有人能够指正错误而写。
多线程的同步与信息传递靠三个工具:旗语,信箱和事件
1.旗语:
旗语是一个装有钥匙的桶,用于多个线程需要共享同一资源时使用,谁拿到规定数量的钥匙,谁可以推进线程进入到下一步。
它是一个内建的类,构造函数new的参数为投入的钥匙数量,默认为0。
方法有get(),put(),try_get(),这三者传参都是可设置的钥匙数量,默认为1。
put()的传参为传入的钥匙数量,不会发生阻塞,可以一直放钥匙进去。
其中try_get()在使用时,不会阻塞线程推进。如果try_get()获得了对应的钥匙数量,则返回1,否则为0。
get()和try_get()都是将钥匙拿出来,而不是拿出它的复制。
我用它的原因是:
在driver中我分次驱动了一部分数据,monitor采集的时候不能够区分这些数据的起始和结束,我需要在driver中驱动完一次数据时给个标志位,这个标志位由旗语产生一个钥匙,只有monitor获得这个钥匙以后,会完成一次采集。
我之所以用旗语而不用事件和信箱的原因是:
事件:事件的方法是@和wait,它们是blocking的属性,我需要在得不到标志位时,monitor需要做其他事情,而不是等待。
信箱:信箱可以传递句柄等参数,这里用旗语比较合适。
2. 事件:
事件是对特定信号的捕捉,只传递信号变化的信息,是对单一,简单的信号控制。
触发的方法是->, 捕捉的主要方法是用@和wait, 看IEEE语法定义中还有其他方法,没有细读。
两者有相同点和不同点:
wait和@区别:wait可以保证同一时刻触发的信号能够在同时刻接受,但在循环语句中必须添加时钟推动,否则会suspend。@在同时刻触发和接收可能会导致竞争冒险现象,但是循环中使用不需要时钟推动。
3.信箱:
信箱的功能强大一些,它不仅能够同步,还能够传递数据信息。
信箱也是一个类,可以在new的时候填入参数 深度。默认为无限大的深度,如果需要做线程同步,则要设置信箱的具体深度。
信箱的put方法和旗语不同,信箱在设置了固定深度后,如果信箱满了,则不能够再put信件进去,而旗语是可以一直put钥匙进去。所以信箱多一个方法就是try_put。
信箱还有peek方法,就是获取信箱中信件的复制,而信件本身还在信箱内。
信箱还可以设置为固定参数类型的信箱,意思就是可以规定该信箱的存取必须是该类型变量,否则会出错。
26

被折叠的 条评论
为什么被折叠?



