2010-11-02 52 views
5

我很新的C#和我想问,如果我在多线程技术情况(伪代码):锁定在多个线程的变量

public class ClassA 
{ 
    ClassB c = new ClassB(); 
    public void someMethod() 
    { 
      c.myVar = 1; 
      // Some other stuff 
      c.myVar = 0; 
    } 
} 

public class ClassB 
{ 
    private int myVar; 

    public void MethodA() 
    { 
     if(myVar = 1) 
       myVar = 0; 
    } 
} 

如果的someMethod()了methodA()可以在单独的线程中处于活动状态,则MethodA()可以将if语句评估为true;但在它设置myVar = 0之前,someMethod设置myVar = 0,因此在MethodA()中将myVar设置为0是不正确的!我可以在myVar的属性(set,get)上锁定{}还是需要使用Interlock(我还没有互锁的经验)?

+2

1)不要为c类型调用一个ClassB类型的变量,多数民众赞成混淆。 – 2010-11-02 20:54:56

+1

你是不是指'if(myVar == 1)'? – Vlad 2010-11-02 20:55:09

+2

2)你不能访问c.myVar,因为它是ClassB的私有成员。 – 2010-11-02 20:55:29

回答

1

这就是我的做法。

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; } } 
    } 
+1

不,这是完全没有用的,在这种情况下,this._myVar的读写是根据c#规范原子化的。 (因为它是一个int)。需要锁定来处理'if(myVar == 1)myVar = 0'的情况,而没有另一个线程改变myVar的可能性,让我们说2之间。 – 2010-11-02 20:59:21

+0

Albin - 请你能解释一下为什么这不起作用? – SimpleOne 2010-11-02 21:21:52

+0

Albin,你错了。如果“myVar = value”是原子的,为什么在Interlocked类中会有一个Exchange()方法?答案是写入不是原子的。 http://msdn.microsoft.com/en-us/library/d3fxt78a.aspx – 2010-11-02 21:54:17

-1

有你有多个线程共享类的同一个实例,而不是实施每个线程,以便它在其范围内得到你的类自己的实例理由吗?

3

它看起来像你试图实现某种信号机制。您可以使用.NET库中提供的其中一个类,例如ManualResetEvent,而不是编写自己的代码。周围

private readonly object _locker = new object(); 
在你的属性get/set方法

然后,锁:

15

您应该创建一个私有对象,将允许锁定

get { lock (_locker) { return this.myVar; } } 
set { lock (_locker) { this.myVar = value; } } 

确保你的方法是使用锁也:

public void MethodA() 
{ 
    lock(_locker) 
    { 
     if(myVar == 1) 
      myVar = 0; 
    } 
} 
+0

我是否需要为{{}}设置类似的锁定? – SimpleOne 2010-11-02 21:20:37

+0

是的,如果你需要一个setter。我会更新 – aqwert 2010-11-02 21:39:35

+0

这是如何解决'someMethod'中的竞争条件? – 2010-11-03 18:45:10

1

我肯定会重新考虑你的整体方法,但如果你是想g从代码的不同部分同步访问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; 
    } 
    } 
}