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

我需要在C.NET中创建一个线程安全的静态变量

  •  11
  • Storm  · 技术社区  · 15 年前

    好吧,这比问题要复杂一点。

    class A
    {
       static int needsToBeThreadSafe = 0;
    
       public static void M1()
       {
         needsToBeThreadSafe = RandomNumber();
       }
    
       public static void M2()
       {
         print(needsToBeThreadSafe);
       }
    }
    

    现在,我需要在m1()和m2()之间调用“needstobethreadsafe”保持线程安全。

    7 回复  |  直到 14 年前
        1
  •  19
  •   paracycle    15 年前

    你可能想问的是[ 线程静态的 属性。如果需要使用类的每个线程 A 拥有自己独立的价值 needsToBeThreadSafe 然后你只需要用[ 线程静态的 属性。

    有关更多信息,请参阅 MSDN documentation for ThreadStaticAttribute .

        2
  •  21
  •   cosmo    14 年前

    怎么样:

    public static void M1()
    {
        Interlocked.Exchange( ref needsToBeThreadSafe, RandomNumber() );
    }
    
    public static void M2()
    {
        print( Interlocked.Read( ref needsToBeThreadSafe ) );
    }
    
        3
  •  8
  •   Adam Robinson    15 年前

    您有两个选择:给出的代码最简单的是 volatile 关键字。声明 needsToBeThreadSafe 作为 static volatile int 这将保证引用该变量的任何线程都将得到“最新”副本,并且该变量不会缓存在代码中。

    也就是说,如果你想更广泛地确保 M1() M2() 执行“原子化”(或至少彼此独占),然后要使用 lock . 最干净的语法是使用“lock block”,如下所示:

    private static object locker = new Object();
    
    //..
    
    public static void M1()
    {
        lock(locker)
        {
            //..method body here
        }
    }
    
    public static void M2()
    {
        lock(locker)
        {
            //..method body here
        }
    }
    

    至于采用哪种方法,这取决于您自己,应该由代码决定。如果您所需要的只是确保将成员分配传播到所有线程并且不缓存,那么 不稳定的 关键字比较简单,可以做得很好。如果超出了这个范围,你可能会想 .

        4
  •  4
  •   Arsen Mkrtchyan    15 年前
    class A
    {
       static int needsToBeThreadSafe = 0;
       static object statObjLocker = new object();
    
       public static void M1()
       {
           lock(statObjLocker)
           {
              needsToBeThreadSafe = RandomNumber();
           }
       }
    
       public static void M2()
       {
           lock(statObjLocker)
           {
              print(needsToBeThreadSafe);
           }
       }
    }
    
        5
  •  2
  •   C. Ross trotttrotttrott    15 年前

    听起来你需要一个 Volatile 成员。

    static volatile int needsToBeThreadSafe = 0;
    
        6
  •  2
  •   Jeppe Stig Nielsen    15 年前

    您还可以使用readerwriterlockslim,这对于多次读取和更少的写入更有效:

    static int needsToBeThreadSafe = 0;
    static System.Threading.ReaderWriterLockSlim rwl = new System.Threading.ReaderWriterLockSlim();
    
    public static void M1()
    {
        try
        {
            rwl.EnterWriteLock();
            needsToBeThreadSafe = RandomNumber();
        }
        finally
        {
            rwl.ExitWriteLock();
        }
    
    }
    
    public static void M2()
    {
        try
        {
            rwl.EnterReadLock();
            print(needsToBeThreadSafe);
        }
        finally
        {
            rwl.ExitReadLock();
        }
    }
    
        7
  •  2
  •   Henk Holterman    15 年前

    首先,我同意使用 lock() 这是最安全的方法。

    但是存在一种更简单的方法,您的示例代码只显示使用 needsToBeThreadSafe 从那时起 int 是原子的,您只需要防止编译器使用volatile进行缓存:

    class A
    {
       static volatile int needsToBeThreadSafe = 0;
    
    }
    

    但是,如果需要在多个语句上使用'threadsafe',请使用一个锁。