两线程间无锁进行数据同步

来源:互联网 发布:淘宝里怎么贷款 编辑:程序博客网 时间:2024/06/06 03:03

线程间数据同步常用的方法就是加锁,但会引发程序挂起延迟的现象,在实时性较高的程序中不可取。


而无锁编程也有很多方法,如

http://www.ibm.com/developerworks/cn/linux/l-cn-lockfree/index.html

文章中,对多不同层级的数据同步方法有着详细的介绍。


据其介绍,两线程间环形缓存区无锁的方法能够比较好的解决读写问题。


我采用环形队列作为环形缓冲区的数据结构。

环形队列的实现方式也可分为线性和链式。对数据个数大小已知或在某个范围内控的情况,采用线性结构的队列,效率比较高;而对数据数量未知的情况,可采用链式结构。

在组织数据结构时,应小心以下几点:

1. 此解决方法适用于两线程间的读写问题;

2. 读者与写者必须先读写数据,后更新索引;

3. 读者线程只操作(更改)头索引,写者线程只操作(更改)尾索引,不能某线程同时操作两个索引。

4. 注意读写可能会发生溢出overflow的状况。读写前,进行判空与满的操作,若满,则需要丢数据。

5. 对线性环形队列的容量,可以设置为2^n,目的是提高循环操作取模%的效率(索引是单向递增的情况)。


对于溢出丢数据的情况,改进方法:

1. 对溢出的数据另外保存,然后加锁同步。这是个解决方法,但本身违背了原来无锁的初衷。

2. 采用链式结构作为缓冲区,数据操作频繁情况下,空间与时间的效率可能较低。嵌入式下,数据结构尽量有一个大小的限制,毕竟资源是有一定限制的,特别是在多个大的应用程序同时运行的状况下。

3. 两个队列,一个线性,一个链式,非溢出时使用线性队列处理数据;在溢出时,采用链式保存溢出的数据。够麻烦吧,效率与复杂度有时就是矛盾。

4. 丢就丢了吧,多测试丢包的情形,设置一个合理的大小,尽量减少丢数据的情况,不过,偶尔发生时,丢就丢了吧。


以上,仅仅是对两线程间数据传递的场景,无需加锁。若是多个线程同时读数据,就需要对读数据时,更改队列的代码加保护,加互斥器;同理,若是多个线程写数据,也需要对写队列的代码加互斥量。否则,仍会可能由于线程竞争造成数据被破坏的情况。 当然,写数据,和读数据 采用不同的互斥器。

----------------

今天跟几个做嵌入式的同事讨论,嵌入式下能否使用c++ STL,他们都不怎么应用STL的,原因是资源毕竟有限。

不过看网上的讨论,很多人还是支持使用STL,在编译器支持的情况下,提高开发效率。

在使用时,尽量注意下资源的使用情况,比如数据结构的大小有个限制,不要无限增大。(可能,随着软硬件资源的扩展,这种情况根本不用考虑了)


原创粉丝点击