数组和线程安全访问

如果我有一个可以/将在任何给定时间点被多个线程访问的数组,究竟是什么导致它是非线程安全的,以及为确保该数组在大多数情况下是线程安全所采取的步骤情况呢?

我已经在互联网上广泛了解并且发现很少或没有关于这个主题的信息,一切似乎都是特定的场景(例如,这个数组,这两个线程通过这两个线程安全地访问,然后开启,等等)。 我真的希望有人可以回答我在顶部提出的问题,或者是否有人可以指出一份解释所述项目的好文件。

编辑:浏览MSDN后,我找到了ArrayList类。 使用synchronize方法时,它返回给定列表的线程安全包装器。 在列表中设置数据时(即list1 [someNumber] = anotherNumber;)包装器会自动处理锁定列表,还是需要锁定它?

当两个线程访问完全相同的资源(例如,不是本地副本,但实际上是相同资源的相同副本)时,可能会发生许多事情。 在最明显的情况下,如果线程#1正在访问资源而线程#2在读取过程中将其更改,则可能会发生一些不可预测的行为。 即使使用像整数这样简单的东西,也可能出现逻辑错误,所以试着想象一下因不正确地使用更复杂的东西而导致的恐怖,比如声明为静态的数据库访问类。

处理此问题的经典方法是锁定敏感资源,因此一次只有一个线程可以使用它。 因此,在上面的示例中,线程#1将请求锁定资源并被授予它,然后继续读取它需要读取的内容。 线程#2将在读取中间并请求锁定资源,但是被拒绝并被告知等待,因为线程#1正在使用它。 当线程#1完成时,它会释放锁定,并且线程#2可以继续。

还有其他情况,但这说明了最基本的问题和解决方案之一。 在C#中,您可以:

1)使用框架可管理的特定.NET对象(如Scorpion-Prince的SynchronizedCollection链接 )

2)使用[MethodImpl(MethodImplOptions.Synchronized)]来指示执行危险操作的特定方法一次只能由一个线程使用

3)使用lock语句隔离正在执行某些潜在危险的特定代码行

什么方法最好的取决于你的情况。

如果我有一个可以/将在任何给定时间点被多个线程访问的数组,究竟是什么导致它是非线程安全的,以及为确保该数组在大多数情况下是线程安全所采取的步骤情况呢?

一般而言,数组不是线程安全的这一事实是,如果您不同步对数组的访问,则两个或多个线程可能正在修改数组的内容。

一般来说,例如,让我们假设你有线程1做这项工作:

for (int i = 0; i < array.Length; i++) { array[i] = "Hello"; } 

并且线程2执行此工作(在相同的共享arrays上)

 for (int i = 0; i < array.Length; i++) { array[i] = "Goodbye"; } 

没有任何同步线程的东西,所以你的结果将取决于哪个线程首先赢得比赛。 它可以是“Hello”或“Goodbye”,以某种随机顺序,但始终至少是“Hello”或“Goodbye”。

CLR保证字符串'Hello'或'Goodbye'的实际写入是primefaces的。 也就是说,试图写'Goodbye'的线程不能打断写'Hello'值。 一个必须在另一个之前或之后发生,而不是在两者之间。

因此,您需要创建某种同步机制以防止arrays互相踩踏。 您可以通过在C#中使用lock语句来完成此操作。

C#3.0及更高版本提供了一个名为SynchronizedCollection的generics集合类,它“提供了一个线程安全的集合,其中包含generics参数指定的类型的对象作为元素。”

如果数组被命名为publicstatic关键字 – 不保证是即时的 – 则Array是线程安全的,因为System.Array实现了ICollection接口,该接口定义了一些同步方法来支持同步机制。

但是,编译枚举数组的项目并不安全,开发人员应该实现lock语句以确保在数组枚举期间没有对数组进行更改。

EX:

 Array arrThreadSafe = new string[] {"We", "are", "safe"}; lock(arrThreadSafe.SyncRoot) { foreach (string item in arrThreadSafe) { Console.WriteLine(item); } }