在多个线程中锁定一个变量。

时间:2023-01-28 10:47:16

I am very new to C# and I wanted to ask if I have this situation in MULTI THREADS (pseudo code):

我对c#非常陌生,我想问一下我是否有多线程的情况(伪代码):

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

public class ClassB
{
     internal int myVar;

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

If someMethod() and MethodA() can be active in separate threads, then MethodA() could evaluate the if statement as true; but before it sets myVar = 0, someMethod() sets myVar = 0 making it incorrect to have set myVar to 0 in MethodA()!!

如果someMethod()和MethodA()可以在单独的线程中活动,那么MethodA()可以评估If语句是否为真;但是在设置myVar = 0之前,someMethod()设置myVar = 0,使得在MethodA()中设置myVar为0是不正确的!!

Basically, how do I lock myVar:

基本上,我如何锁定myVar:

  • can I lock{} on myVar's property (set, get)
  • 我可以锁定myVar的属性(设置,get)
  • do I need to use Interlock (I have no experience yet of Interlock though)?
  • 我需要使用联锁吗(我还没有联锁的经验)?

5 个解决方案

#1


16  

You should create a private object that will allow for locking:

您应该创建一个允许锁定的私有对象:

private readonly object _locker = new object();

Then in your property get/set methods, lock around it:

然后在你的属性中获取/设置方法,锁定它:

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

Make sure your method uses the lock also:

确保你的方法也使用锁:

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

#2


3  

It looks like you are trying to implement some sort of signalling mechanism. Instead of writing your own you could use one of the classes provided in the .NET library such as ManualResetEvent.

看起来你在尝试实现某种信号机制。您可以使用。net库中提供的一个类,例如ManualResetEvent,而不是自己编写。

#3


1  

This is how I do it.

我就是这么做的。

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

#4


1  

I would certainly rethink your overall approach, but if you are wanting to synchronize access to the members of ClassB from different sections of code then you could steal a not-so-good design pattern from the ICollection interface and expose a SyncRoot property that can be used to acquire the same lock as the original instance.

我肯定会考虑整体的方法,但是如果你想要同步访问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;
    }
  }
}

#5


-1  

Is there a reason you have multiple threads sharing the same instance of your class instead of implementing each thread so that it gets its own instance of your class within its scope?

您是否有理由让多个线程共享类的同一个实例,而不是实现每个线程,以便在其范围内获得类的自己的实例?

#1


16  

You should create a private object that will allow for locking:

您应该创建一个允许锁定的私有对象:

private readonly object _locker = new object();

Then in your property get/set methods, lock around it:

然后在你的属性中获取/设置方法,锁定它:

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

Make sure your method uses the lock also:

确保你的方法也使用锁:

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

#2


3  

It looks like you are trying to implement some sort of signalling mechanism. Instead of writing your own you could use one of the classes provided in the .NET library such as ManualResetEvent.

看起来你在尝试实现某种信号机制。您可以使用。net库中提供的一个类,例如ManualResetEvent,而不是自己编写。

#3


1  

This is how I do it.

我就是这么做的。

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

#4


1  

I would certainly rethink your overall approach, but if you are wanting to synchronize access to the members of ClassB from different sections of code then you could steal a not-so-good design pattern from the ICollection interface and expose a SyncRoot property that can be used to acquire the same lock as the original instance.

我肯定会考虑整体的方法,但是如果你想要同步访问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;
    }
  }
}

#5


-1  

Is there a reason you have multiple threads sharing the same instance of your class instead of implementing each thread so that it gets its own instance of your class within its scope?

您是否有理由让多个线程共享类的同一个实例,而不是实现每个线程,以便在其范围内获得类的自己的实例?