Блокировка переменной в нескольких потоках - PullRequest
6 голосов
/ 02 ноября 2010

Я очень новичок в C #, и я хотел спросить, есть ли у меня такая ситуация в MULTI THREADS (псевдокод):

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

Если someMethod() и MethodA() могут быть активны в отдельных потокахтогда MethodA() может оценить оператор if как true;но прежде чем он установит myVar = 0, someMethod() устанавливает myVar = 0, что делает неправильным установку myVar в 0 в MethodA() !!

По сути, как мне заблокировать myVar:

  • могу ли я lock{} на свойстве myVar (установить, получить)
  • мне нужно использовать Interlock (хотя у меня пока нет опыта Interlock)?

Ответы [ 5 ]

16 голосов
/ 02 ноября 2010

Вы должны создать частный объект, который позволит блокировать:

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;
    }
}
3 голосов
/ 02 ноября 2010

Похоже, вы пытаетесь реализовать какой-то механизм сигнализации.Вместо написания своего собственного вы можете использовать один из классов, предоставляемых в библиотеке .NET, например ManualResetEvent.

1 голос
/ 03 ноября 2010

Я бы, конечно, переосмыслил ваш общий подход, но если вы хотите синхронизировать доступ к элементам 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 голос
/ 02 ноября 2010

Вот как я это делаю.

    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; } }
    }
0 голосов
/ 02 ноября 2010

Есть ли причина, по которой у вас несколько потоков, совместно использующих один и тот же экземпляр вашего класса, вместо реализации каждого потока, чтобы он получал свой собственный экземпляр вашего класса в своей области видимости?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...