我正在研究一个拥有多个线程和一个共享对象的系统。有许多线程经常进行读取操作,但写入操作很少,每天可能需要3到5次。
我正在使用rwlock进行同步,但锁定获取操作不够快,因为它一直在发生。所以,我正在寻找一种更快的方法。
也许是一种在写入期间使写入函数成为原子或查找所有线程的方法。可移植性并不是一项硬性要求,我使用的是Linux和GCC 4.6。
答案 0 :(得分:5)
您是否考虑过使用liburcu进行读取 - 复制更新?这使您可以避免原子操作并在读取路径上完全锁定 ,但代价是使写入速度慢得多。请注意,有些读者可能会在短时间内看到陈旧数据;如果您需要更新立即生效,它可能不是您的最佳选择。
答案 1 :(得分:4)
您可能希望使用多个对象而不是单个对象。而不是实际共享对象,创建一个包含对象和原子计数的对象,然后在线程之间共享一个指针到此结构。
[假设只有一个写入者]每个读者都会获得指针,然后原子地递增计数器并使用该对象,在读取后,原子地递减计数器。作者将创建一个新对象,其中包含原始副本并对其进行修改。然后执行两个指针的原子交换。现在问题是释放旧对象,这就是你需要读者数量的原因。作者需要继续检查旧对象的计数,直到所有读者都完成了工作,此时您可以删除旧对象。
如果有多个编写器(即可以有多个线程更新变量),您可以遵循相同的方法,但编写器需要进行指针的比较和交换交换。如果更新副本已更改的指针,则编写器重新启动该进程(删除它的新对象,再次从指针复制并重试CAS)
答案 2 :(得分:1)
也许你可以使用自旋锁,线程会忙着等到解锁。如果线程没有长时间锁定,它可能比互斥锁更有效,因为锁定和解锁完成时指令较少。
spinlock是POSIX pthread的一部分,虽然是可选的,所以我不知道它是否在你的系统上实现。我在ubuntu的C程序中使用它们但是必须使用-std = gnu99而不是c99进行编译。