2

I have a class that has a few arraylists in it.

My main class creates a new instance of this class. My main class has at least 2 threads adding and removing from my class with the arraylists in it. At the moment everything is running fine but I was just wondering if it would be safer to declare my class with the arraylists in it as volatile eg/

private volatile myclass;
myclass = new myclass();
......
myclass.Add(...)
myclass.Clear(..)
4

2 回答 2

4

在此示例中,使用 volatile 关键字不会使您的代码线程安全。volatile 关键字通常用于确保在读取或写入变量(即类字段)的值时,该变量的最新值要么从主存读取,要么直接写入主存,而不是从缓存中读取(例如CPU 寄存器)例如。volatile 关键字是一种表示“不要对这个共享字段使用缓存优化”的方式,它消除了线程可能使用字段的本地副本而看不到彼此更新的问题。

在您的情况下,myclass 的值实际上并没有被更新(即您没有重新分配 myclass),因此 volatile 对您没有用,并且它不是您实际上希望在此线程安全的 myclass 变量的更新无论如何。

如果您希望更新实际的类线程安全,那么在“添加”和“清除”周围使用“锁定”是一种直接的选择。这将确保一次只有一个线程可以执行这些操作(更新 myclass 的内部状态),因此不应并行执行。

可以按如下方式使用锁:

private readonly object syncObj = new object(); 
private readonly myclass = new myclass();
......

lock (syncObj)
{
    myclass.Add(...)
}

lock (syncObj)
{
    myclass.Clear(..)
}

您还需要在读取由“添加”更新的状态的任何代码周围添加锁定,如果是这种情况,尽管它没有出现在您的示例代码中。

在第一次编写多线程代码时,为什么在添加到集合时需要锁可能并不明显。如果我们以 List 或 ArrayList 为例,那么问题就出现了,因为这些集合在内部使用 Array 作为后备存储,并且会动态地“增长”这个 Array(即通过创建一个新的更大的 Array 并复制旧的内容)调用 Add 时满足容量。这一切都发生在内部,需要维护此数组和变量,例如集合的当前大小(而不是可能更大的实际数组的长度)。因此,如果内部 Array 需要增长,添加到集合可能涉及多个步骤。当以不安全的方式使用多线程时,多线程可能会间接导致添加时发生增长,从而践踏彼此的更新。以及多个线程同时添加的问题,还有另一个线程可能试图读取集合的问题内部状态正在改变。使用锁可确保在不受其他线程干扰的情况下完成此类操作。

于 2010-07-28T08:11:45.760 回答
2

At present, the code is wrong; adding a volatile keyword won't fix it. It's not safe to use the .NET classes across threads without adding synchronisation.

It's hard to give straightforward advice without knowing more about the structure of your code. A first step would be to start using the lock keyword around all accesses to the list object; however, there could still be assumptions in the code that don't work across multiple threads.

It's possible to use a collection class that's already safe for multithreaded access, which would avoid the need for getting the lock keyword in the right place, but it's still possible to make errors.

Can you post some more of your code? That way we can give more specific suggestions about making it thread safe.

于 2010-07-28T08:05:21.967 回答