我在这里严重问了一个问题Lock on a variable in multiple threads所以为了清楚起见,我会在这里问一下,希望我能正确地问它。
classA
creates instance of classB
has methodA that can update & uses classB's myVar
has methodB that can update & uses classB's myVar
classB
has a variable myVar
methodA和methodB都可以在不同的线程中运行(在main的新线程中调用)。我如何确保这是线程安全的?
答案 0 :(得分:19)
使用lock
关键字来保护可以由多个线程同时执行的代码。
public class ClassA
{
private ClassB b = new ClassB();
public void MethodA()
{
lock (b)
{
// Do anything you want with b here.
}
}
public void MethodB()
{
lock (b)
{
// Do anything you want with b here.
}
}
}
重要的是要注意lock
不保护或锁定语句中使用的对象实例。相反,如果另一个使用相同对象实例的部分已在执行,则该对象用作标识应阻止执行的代码段的方法。换句话说,您可以在lock
语句中使用您喜欢的任何对象实例,并且访问ClassB
的成员仍然是安全的。
答案 1 :(得分:3)
答案 2 :(得分:0)
查看lock声明文档。
答案 3 :(得分:0)
ClassB
不应该暴露变量(您可能意味着数据成员)。改为展示一个属性或一组方法,并使用ReaderWriterLockSlim来处理多个线程。
答案 4 :(得分:0)
最简单的解决方案:不要在线程中共享ClassB的实例。
换句话说,使用您的线程声明实例化一个新的ClassB并将其作为参数发送。
答案 5 :(得分:0)
不幸的是,这个问题在线程安全性方面被认为是成功的有些含糊不清。线程安全只意味着如果多个线程正在执行,操作将正常工作。
似乎缺少的是classA.methodA或classA.methodB是否需要在调用classA.methodA(...)或classA.methodB(...)的另一个线程之前使用classB.myVar完成其操作。它将确定您需要什么类型的锁定模式。
例如,如果您需要保证读取值,它将如下所示:
public class classA
{
private classB b = new classB();
public void methodA()
{
lock (b)
{
// Operation without calling methodA() or methodB()
// Read b.myVar
// Update b.myVar
}
}
public void methodB()
{
lock (b)
{
// Operation without calling methodA() or methodB()
// Read b.myVar
// Update b.myVar
}
}
}
在另一个例子中,如果b.myVar是需要像缓存一样同步的某种类型的集合,它将如下所示:
public class classA
{
private classB b = new classB();
public void methodA()
{
// Read b.myVar for missing collection item
lock (b)
{
// Check for missing collection item again. If not missing, leave lock
// Operation without calling methodA() or methodB()
// Read b.myVar
// Update b.myVar with new array item
}
}
public void methodB()
{
// Read b.myVar for missing collection item
lock (b)
{
// Check for missing collection item again. If not missing, leave lock
// Operation without calling methodA() or methodB()
// Read b.myVar
// Update b.myVar with new array item
}
}
}