我想知道什么是使数据线程安全的“最佳”方式。
具体来说,我需要跨多个线程保护链表 - 一个线程可能尝试从中读取,而另一个线程从中添加/删除数据,甚至释放整个列表。我一直在读锁;它们似乎是最常用的方法,但显然它们可能存在问题(死锁)。我还读过关于原子操作以及线程本地存储的内容。
在您看来,什么是我最好的行动方案?大多数程序员使用的方法是什么?出于什么原因?
答案 0 :(得分:5)
一种没有大量使用但非常合理的方法是指定一个专用线程来拥有每个“共享”结构。该线程通常等待(线程安全;-)队列,例如在Python中Queue.Queue
实例,用于工作请求(读取或更改共享结构),包括请求响应的那些(它们将通过自己的队列,在准备好时放置响应)和“T。这种方法完全序列化对共享资源的所有访问,轻松地重新映射到多进程或分布式体系结构(几乎无脑,在Python中,multiprocessing
;-),绝对保证健全,缺乏死锁以及种族条件,只要基础队列对象一次性编程良好。
它基本上将共享数据结构的地狱变成了消息传递并发体系结构的天堂。
OTOH,它可能比使用lock& c; - )以强硬的方式阻止它的开销更高。
答案 1 :(得分:2)
你可以考虑一个不可变的集合。就像.net中的字符串如何具有替换,插入等方法一样。它不会修改字符串,而是创建一个新字符串,LinkedList集合也可以设计为不可变的。实际上,与其他一些集合数据结构相比,LinkedList实现起来非常简单。
这是一篇关于讨论不可变集合的博客文章的链接,以及指向.NET中某些实现的链接。
http://blogs.msdn.com/jaredpar/archive/2009/04/06/immutable-vs-mutable-collection-performance.aspx
答案 2 :(得分:0)
始终记住最重要的线程安全规则。从内到外了解代码的所有关键部分。通过这种方式,了解它们就像你的ABC一样。只有当你能够一次性识别它们时,你才会知道操作线程安全机制的区域。
之后,请记住经验法则:
(我相信其他人可以添加更多。)
答案 3 :(得分:0)
从安全的角度来看,“最佳”方式是锁定整个数据结构,以便一次只能触摸一个线程。
一旦你决定锁定少于整个结构,大概是出于性能原因,这样做的细节是混乱的,并且每个数据结构,甚至相同结构的变体都不同。
我的建议是
从数据结构的全局锁定开始。描述你的程序,看看它是否真的有问题。
如果这是一个问题,请考虑是否有其他方法来分发问题。您是否可以最大限度地减少相关数据结构中的数据量,以便不需要经常访问或长时间访问?例如,如果它是一个排队系统,也许您可以为每个线程保留一个本地队列,并且只在本地队列变得过载或负载不足时才将事物移入或移出全局队列。
查看旨在帮助减少对您正在进行的特定类型事物的争用的数据结构,并谨慎而精确地实施它们,在安全方面犯错误。对于排队示例,工作窃取队列可能就是您所需要的。