代码之家  ›  专栏  ›  技术社区  ›  SimpleOne

如何锁定多线程中使用的变量

  •  14
  • SimpleOne  · 技术社区  · 14 年前

    我在这里问了一个问题 Lock on a variable in multiple threads

    classA
      creates instance of classB
      has methodA that can update & uses classB's myVar
      has methodB that can update & uses classB's myVar
    
    classB
      has a variable myVar
    

    methodA和methodB都可以在单独的线程中运行(在main的新线程中调用)。如何确保这是线程安全的?

    6 回复  |  直到 7 年前
        1
  •  21
  •   Brian Gideon    14 年前

    使用 lock 关键字来保护可由多个线程同时执行的代码。

    public class ClassA
    {
      private ClassB b = new ClassB();
    
      public void MethodA()
      {
        lock (b)
        {
          // Do anything you want with b here.
        }
      }
    
      public void MethodB()
      {
        lock (b)
        {
          // Do anything you want with b here.
        }
      }
    }
    

    需要注意的是 不保护或锁定语句中使用的对象实例。相反,如果使用 相同的 对象实例已在执行。换句话说,您可以在 声明和访问 ClassB

        2
  •  3
  •   Erik Noren    14 年前

    我写了一个 blog post 关于让多个线程向列表中添加值并使用 lock()

        3
  •  0
  •   Kon    14 年前

    查看 lock 报表文档。

        4
  •  0
  •   user203570 user203570    14 年前

    ClassB 不应该公开变量(您可能指的是数据成员)。而是公开一个属性或一组方法,并使用 ReaderWriterLockSlim

        5
  •  0
  •   Austin Salonen gmlacrosse    14 年前

    最简单的解决方案是:不要在线程之间共享ClassB实例。

    换句话说,用线程声明实例化一个新的类B,并将其作为参数发送。

        6
  •  0
  •   Frank Liao    14 年前

    不幸的是,这个问题在线程安全方面有点模棱两可。线程安全只是指如果多个线程正在执行,则操作将正常工作。

    似乎缺少的是classA.methodA或classA.methodB是否需要在另一个调用classA.methodA(…)或classA.methodB(…)的线程之前使用classB.myVar完成其操作。它将决定您需要什么类型的锁定模式。

    例如,如果您需要一个读取值的保证,它将如下所示:

    public class classA
    {
        private classB b = new classB();
    
        public void methodA()
        {
            lock (b)
            {
                // Operation without calling methodA() or methodB() 
                // Read b.myVar
                // Update b.myVar
            }
        }
    
        public void methodB()
        {
            lock (b)
            {
                // Operation without calling methodA() or methodB()
                // Read b.myVar
                // Update b.myVar
            }
        }
    }
    

    public class classA
    {
        private classB b = new classB();
    
        public void methodA()
        {
            // Read b.myVar for missing collection item
    
            lock (b)
            {
                // Check for missing collection item again. If not missing, leave lock
                // Operation without calling methodA() or methodB() 
                // Read b.myVar
                // Update b.myVar with new array item
            }
        }
    
        public void methodB()
        {
            // Read b.myVar for missing collection item
            lock (b)
            {
                // Check for missing collection item again. If not missing, leave lock
                // Operation without calling methodA() or methodB() 
                // Read b.myVar
                // Update b.myVar with new array item
            }
        }
    }