Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在多个线程中锁定一个变量_C#_Multithreading_Variables_Locking - Fatal编程技术网

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

我对C#非常陌生,我想问一下在多线程(伪代码)中是否存在这种情况:

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