线程安全......我的“最好”是什么? 行动方针?

发布于 2024-07-24 06:20:11 字数 225 浏览 8 评论 0原文

我想知道使数据线程安全的“最佳”方法是什么。

具体来说,我需要跨多个线程保护链表 - 一个线程可能会尝试从中读取数据,而另一个线程从中添加/删除数据,甚至释放整个列表。 我一直在阅读有关锁的内容; 它们似乎是最常用的方法,但显然它们可能会出现问题(死锁)。 我还阅读了有关原子操作以及线程本地存储的内容。

您认为我最好的行动方案是什么? 大多数程序员使用的方法是什么?原因是什么?

I'm wondering what is the "best" way to make data thread-safe.

Specifically, I need to protect a linked-list across multiple threads -- one thread might try to read from it while another thread adds/removes data from it, or even frees the entire list. I've been reading about locks; they seem to be the most commonly used approach, but apparently they can be problematic (deadlocks). I've also read about atomic-operations as well as thread-local storage.

In your opinion, what would be my best course of action? What's the approach that most programmers use, and for what reason?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

前事休说 2024-07-31 06:20:11

一种使用不多但相当合理的方法是指定一个特殊用途的线程来拥有每个“共享”结构。 该线程通常位于(线程安全;-)队列上等待工作请求(读取或更改共享结构),例如在 Python 中的 Queue.Queue 实例,包括请求响应(他们将传递自己的队列,准备好后将响应放置在该队列上)和没有的响应。 这种方法完全序列化对共享资源的所有访问,轻松地重新映射到多进程或分布式架构(在 Python 中,使用 multiprocessing;- 几乎是无脑的),并且绝对保证了健全性并且没有死锁,如下所示:以及竞争条件,只要底层队列对象经过良好编程即可一劳永逸。

它基本上将共享数据结构的地狱变成了消息传递并发架构的天堂。

OTOH,它可能比用锁硬碰硬的开销要高一点&c;-)。

One approach that is not heavily used, but quite sound, is to designate one special purpose thread to own every "shared" structure. That thread generally sits waiting on a (thread-safe;-) queue, e.g. in Python a Queue.Queue instance, for work requests (reading or changing the shared structure), including both ones that request a response (they'll pass their own queue on which the response is placed when ready) and ones that don't. This approach entirely serializes all access to the shared resource, remaps easily to a multi-process or distributed architecture (almost brainlessly, in Python, with multiprocessing;-), and absolutely guarantees soundness and lack of deadlocks as well as race conditions as long as the underlying queue object is well-programmed once and for all.

It basically turns the hell of shared data structures into the paradise of message-passing concurrency architectures.

OTOH, it may be a tad higher-overhead than slugging it out the hard way with locks &c;-).

回忆躺在深渊里 2024-07-31 06:20:11

您可以考虑一个不可变的集合。 就像 .net 中的字符串具有 Replace、Insert 等方法一样。它不会修改字符串,而是创建一个新字符串,LinkedList 集合也可以设计为不可变的。 事实上,与其他一些集合数据结构相比,LinkedList 的实现方式实际上相当简单。

下面是讨论不可变集合的博客文章的链接以及 .NET 中一些实现的链接。

http://blogs. msdn.com/jaredpar/archive/2009/04/06/immutable-vs-mutable-collection-performance.aspx

You could consider an immutable collection. Much like how a string in .net has methods such as Replace, Insert, etc. It doesn't modify the string but instead creates a new one, a LinkedList collection can be designed to be immutable as well. In fact, a LinkedList is actually fairly simple to implement this way as compared to some other collection data structures.

Here's a link to a blog post discussing immutable collections and a link to some implementations in .NET.

http://blogs.msdn.com/jaredpar/archive/2009/04/06/immutable-vs-mutable-collection-performance.aspx

日裸衫吸 2024-07-31 06:20:11

永远记住线程安全最重要的规则。 彻底了解代码的所有关键部分。 这样,就像了解 ABC 一样了解它们。 只有当你在被询问时能够识别它们,你才会知道在哪些区域操作你的线程安全机制。

之后,请记住经验法则:

  • 留意您的所有全局信息
    变量/堆上的变量。
  • 确保你的子程序是
    可重入。
  • 确保可以访问共享数据
    连载了。
  • 确保没有间接的
    通过指针访问。

(我相信其他人可以添加更多。)

Always remember the most important rule of thread safety. Know all the critical sections of your code inside out. And by that, know them like your ABCs. Only if you can identify them at go once asked will you know which areas to operate your thread safety mechanisms on.

After that, remember the rules of thumb:

  • Look out for all your global
    variables / variables on the heap.
  • Make sure your subroutines are
    re-entrant.
  • Make sure access to shared data is
    serialized.
  • Make sure there are no indirect
    accesses through pointers.

(I'm sure others can add more.)

泪痕残 2024-07-31 06:20:11

从安全角度来看,“最好”的方法是对整个数据结构加一把锁,以便一次只有一个线程可以接触它。

一旦您决定锁定少于整个结构(可能是出于性能原因),执行此操作的细节就会很混乱,并且对于每个数据结构甚至同一结构的变体都不同。

我的建议是

  1. 从数据结构上的全局锁开始。 分析您的程序以查看是否确实存在问题。

  2. 如果这是一个问题,请考虑是否有其他方法来分配问题。 您能否最大限度地减少相关数据结构中的数据量,以便不需要如此频繁或长时间地访问它? 一个排队系统,也许您可​​以为每个线程保留一个本地队列,并且仅当本地队列过载或负载不足时才将内容移入或移出全局队列。

  3. 查看旨在帮助减少您正在做的特定类型事情的争用的数据结构,并仔细而精确地实现它们,在安全方面犯错误。 对于排队示例,工作窃取队列可能正是您所需要的。

The "best" way, from a safety point of view, is to put a lock on the entire data structure, so that only one thread can touch it at a time.

Once you decide to lock less than the entire structure, presumably for performance reasons, the details of doing this are messy and differ for every data structure, and even variants of the same structure.

My suggestion is to

  1. Start with a global lock on your data structure. Profile your program to see if it's really a problem.

  2. If it is a problem, consider whether there's some other way to distribute the problem. Can you minimize the amount of data in the data structure in question, so that it need not be accessed so often or for so long? If it's a queuing system, for example, perhaps you can keep a local queue per thread, and only move things into or out of a global queue when a local queue becomes over- or under-loaded.

  3. Look at data structures designed to help reduce contention for the particular type of thing you're doing, and implement them carefully and precisely, erring on the side of safety. For the queuing example, work-stealing queues might be what you need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文