C# 在多个线程中锁定一个变量
我对C#非常陌生,我想问一下在多线程(伪代码)中是否存在这种情况: 如果C# 在多个线程中锁定一个变量,c#,multithreading,variables,locking,C#,Multithreading,Variables,Locking,我对C#非常陌生,我想问一下在多线程(伪代码)中是否存在这种情况: 如果someMethod()和MethodA()可以在单独的线程中处于活动状态,那么MethodA()可以将If语句计算为true;但是在设置myVar=0之前,someMethod()设置myVar=0使得在MethodA()中将myVar设置为0是不正确的 基本上,如何锁定myVar: 我可以对myVar的属性(set,get)锁定{}吗 我是否需要使用联锁(不过我还没有联锁的经验) 我就是这样做的 static
someMethod()
和MethodA()
可以在单独的线程中处于活动状态,那么MethodA()
可以将If语句计算为true;但是在设置myVar=0
之前,someMethod()
设置myVar=0
使得在MethodA()中将myVar
设置为0是不正确的
基本上,如何锁定myVar
:
- 我可以对
myVar
的属性(set,get)锁定{}
吗
联锁
(不过我还没有联锁
的经验)- 我就是这样做的
static readonly object _myVar_Lock = new object();
private int _myVar = 0;
public int myVar
{
get { lock (_myVar_Lock) { return this._myVar; } }
set { lock (_myVar_Lock) { this._myVar = value; } }
}
看起来您正在尝试实现某种信号机制。您可以使用.NET库中提供的类之一,而不是编写自己的类,例如。您应该创建一个允许锁定的私有对象:
private readonly object _locker = new object();
然后在属性get/set方法中,锁定它:
get { lock (_locker) { return this.myVar; } }
set { lock (_locker) { this.myVar = value; } }
确保您的方法也使用锁:
public void MethodA()
{
lock(_locker)
{
if(myVar == 1)
myVar = 0;
}
}
我肯定会重新考虑你的总体方针,但是,如果您希望从不同的代码段同步对
ClassB
成员的访问,那么您可以从ICollection
接口窃取一个不太好的设计模式,并公开一个SyncRoot
属性,该属性可用于获取与原始实例相同的锁
public class ClassA
{
private ClassB c = new ClassB();
public void someMethod()
{
lock (c.SyncRoot)
{
c.MyVar = 1;
// Some other stuff
c.MyVar = 0;
}
}
}
public class ClassB
{
private object m_LockObject = new object();
private int m_MyVar;
public object SyncRoot
{
get { return m_LockObject; }
}
public int MyVar
{
get { lock (SyncRoot) return m_MyVar; }
set { lock (SyncRoot) m_MyVar = value; }
}
public void MethodA()
{
lock (SyncRoot)
{
if (m_MyVar == 1) m_Var = 0;
}
}
}
1) 不要为c调用ClassB类型的变量,这很容易混淆。你的意思是
如果(myVar==1)
?2)你不能访问c.myVar,因为它是ClassB的私有成员。你在问题中描述的是ClassA和ClassB的定义。不过,您需要描述这些在线程中的使用方式。例如,如果您有创建ClassA实例的Thread1和创建ClassB实例的Thread2,那么Thread1中的ClassA.c变量将与Thread2中的ClassB实例不同(在内存中)。因此,在本例中,您不需要锁,因为您没有使用相同的对象实例。如果myVar
已设置为零,为什么将其设置为零是不正确的?因为设置一个字段是一个幂等运算,所以我不认为两次设置字段是“错误的”。你能再解释一下你想解决什么问题吗?不,这是完全没有用的,读写这篇文章。_myVar在本例中是c#spec的原子(因为它是int)。如果(myVar==1)myVar=0,则需要锁定来处理案例代码>如果没有另一个线程将myVar更改为介于两者之间的2个线程的可能性。Albin-请您进一步解释一下为什么这不起作用?Albin,您错了。如果“myVar=value”是原子的,为什么在联锁类上会有一个Exchange()方法?答案是写入不是原子的@OJ,写是原子的,但读写组合不是原子的。当您输入属性设置器时,您已经执行了读取,因此在属性设置器中拥有锁是没有用的。锁的唯一可能好处是它在字段上设置了一个内存屏障(类似于将其标记为volatile),但这并不能解决更高级别的同步问题。我是否需要为set{}设置一个类似的锁?这如何解决someMethod
中的争用条件?
public class ClassA
{
private ClassB c = new ClassB();
public void someMethod()
{
lock (c.SyncRoot)
{
c.MyVar = 1;
// Some other stuff
c.MyVar = 0;
}
}
}
public class ClassB
{
private object m_LockObject = new object();
private int m_MyVar;
public object SyncRoot
{
get { return m_LockObject; }
}
public int MyVar
{
get { lock (SyncRoot) return m_MyVar; }
set { lock (SyncRoot) m_MyVar = value; }
}
public void MethodA()
{
lock (SyncRoot)
{
if (m_MyVar == 1) m_Var = 0;
}
}
}