锁对象数组可用于保证对 MyClassArray 的线程安全访问?
Posted
技术标签:
【中文标题】锁对象数组可用于保证对 MyClassArray 的线程安全访问?【英文标题】:Array of lock objects can be used to guarantee thread safe access to MyClassArray? 【发布时间】:2021-01-10 22:57:34 【问题描述】:我有一个 MyClassArray[fixed lentgh N] 我想保证每个元素的线程安全访问。当我需要使用一个元素时,我不想锁定整个数组。我想知道锁定对象的相同大小的 lockArray 是否每当我想从 MyClassArray 访问元素 i 时,我都会执行 Monitor.Enter(lockArray[i]) 对 MyClassArray[i] 的访问将是线程安全的。我担心的是并发访问 lockArray[i] 是否会搞砸。 对不起,如果这太天真了,或者这个问题有另一个简单的解决方案。我是多线程和 C# 的新手。
Rgds, 克里斯蒂亚诺
【问题讨论】:
使用专用的锁定对象,不要锁定数组本身。 Overview of synchronization primitives & Synchronizing data for multithreading & How does lock work exactly? & Monitor And Lock In C# (C-SharpCorner). 它是否安全在很大程度上取决于你正在做什么以及它是如何实施的细节。没有人能准确地说明尚未编写的代码的正确性。 @OlivierRogier 该问题不建议直接锁定任何阵列。也就是说,如果它暴露在处理其同步的类之外,它真的只是一个问题。 @Servy,我怀疑两个线程是否同时尝试执行 Monitor.Enter(lockArray[i]) 是否可行并保证只有一个线程可以访问,直到Monitor.Exit。或者,如果我需要在静态 lock 块内执行此 Monitor.Enter(lockArray[i])。 @ChristianoPereira 如果没有真正看到具体细节,没有人能正确回答这个问题。 【参考方案1】:假设您有两个相同大小的数组values
和locks
:
int[] values = Enumerable.Range(0, 100).ToArray();
object[] locks = Enumerable.Range(0, 100).Select(_ => new object()).ToArray();
...你想用locks
的对应元素来保护values
的每个元素:
lock (locks[13])
values[13] += 1;
...这是完全线程安全的,前提是:
初始化
的locks
数组将在启动将执行处理的线程或任务之前发生。否则您可能会遇到可见性问题(可以通过Thread.MemoryBarrier
和其他方式解决,但您最好避免这种复杂性)。
values
数组的每个元素都可以独立于其他元素进行变异。否则,如果您发现需要像这样创建嵌套锁:
lock (locks[13])
lock (locks[14])
values[13] += values[14];
...那么您可能遇到了麻烦(您可能必须解决Five Dining philosophers 问题以防止死锁)。
【讨论】:
1 和 2 对我的应用程序来说不是问题。感谢您的回答!我将遵循该实现。以上是关于锁对象数组可用于保证对 MyClassArray 的线程安全访问?的主要内容,如果未能解决你的问题,请参考以下文章