zoukankan      html  css  js  c++  java
  • C#线程同步

    一、volatile关键字

      volatile是最简单的一种同步方法,当然简单是要付出代价的。它只能在变量一级做同步,volatile的含义就是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我。(【转自www.bitsCN.com 】)因此,当多线程同时访问该变量时,都将直接操作主存,从本质上做到了变量共享。

      能够被标识为volatile的必须是以下几种类型:(摘自MSDN)

    • Any reference type.
    • Any pointer type (in an unsafe context).
    • The types sbyte, byte, short, ushort, int, uint, char, float, bool.
    • An enum type with an enum base type of byte, sbyte, short, ushort, int, or uint.
      1 public class A
      2 {
      3 private volatile int _i;
      4 public int I
      5 {
      6 get { return _i; }
      7 set { _i = value; }
      8 }
      9 }

      但volatile并不能实现真正的同步,因为它的操作级别只停留在变量级别,而不是原子级别。如果是在单处理器系统中,是没有任何问题的,变量在主存中没有机会被其他人修改,因为只有一个处理器,这就叫作processor Self-Consistency。但在多处理器系统中,可能就会有问题。 每个处理器都有自己的data cach,而且被更新的数据也不一定会立即写回到主存。所以可能会造成不同步,但这种情况很难发生,因为cach的读写速度相当快,flush的频率也相当高,只有在压力测试的时候才有可能发生,而且几率非常非常小。

       二、lock关键字

        lock是一种比较好用的简单的线程同步方式,它是通过为给定对象获取互斥锁来实现同步的。它可以保证当一个线程在关键代码段的时候,另一个线程不会进来,它只能等待,等到那个线程对象被释放,也就是说线程出了临界区。用法:

      1 public void Function()
      2 {
      3     System.Object lockThis = new System.Object();
      4     lock(lockThis)
      5     {
      6         // Access thread-sensitive resources.
      7     }
      8 }

      提供给 lock 关键字的参数必须为基于引用类型的对象,该对象用来定义锁的范围。在上例中,锁的范围限定为此函数,因为函数外不存在任何对该对象的引用。严格地说,提供给 lock 的对象只是用来唯一地标识由多个线程共享的资源,所以它可以是任意类实例。然而,实际上,此对象通常表示需要进行线程同步的资源。例如,如果一个容器对象将被多个线程使用,则可以将该容器传递给 lock,而 lock 后面的同步代码块将访问该容器。只要其他线程在访问该容器前先锁定该容器,则对该对象的访问将是安全同步的。

    • 使用 lock 关键字通常比直接使用 Monitor 类更可取,一方面是因为 lock 更简洁,另一方面是因为 lock 确保了即使受保护的代码引发异常,也可以释放基础监视器。这是通过 finally 关键字来实现的,无论是否引发异常它都执行关联的代码块。

       1 System.Object obj = (System.Object)x;
       2 System.Threading.Monitor.Enter(obj);
       3 try
       4 {
       5     DoSomething();
       6 }
       7 finally
       8 {
       9     System.Threading.Monitor.Exit(obj);
      10 }

      三.AutoResetEvent

       1 using System;
       2 using System.Threading;
       3 
       4 class ThreadingExample
       5 {
       6     static AutoResetEvent autoEvent;
       7 
       8     static void DoWork()
       9     {
      10         Console.WriteLine("   worker thread started, now waiting on event...");
      11         autoEvent.WaitOne();
      12         Console.WriteLine("   worker thread reactivated, now exiting...");
      13     }
      14 
      15     static void Main()
      16     {
      17         autoEvent = new AutoResetEvent(false);
      18 
      19         Console.WriteLine("main thread starting worker thread...");
      20         Thread t = new Thread(DoWork);
      21         t.Start();
      22 
      23         Console.WriteLine("main thrad sleeping for 1 second...");
      24         Thread.Sleep(1000);
      25 
      26         Console.WriteLine("main thread signaling worker thread...");
      27         autoEvent.Set();
      28     }
      29 }
  • 相关阅读:
    接水果(fruit)
    大融合
    排序(sortb)
    latex公式测试
    次小生成树
    HDU 2973 YAPTCHA (威尔逊定理)
    状压DP概念 及例题(洛谷 P1896 互不侵犯)
    ICPC Asia Nanning 2017 F. The Chosen One (大数、规律、2的k次幂)
    HDU 1074 Doing Homework (状压DP)
    最长上升(不下降)子序列(LIS) 不同求解方法(动规、贪心)
  • 原文地址:https://www.cnblogs.com/maxiaotiao/p/2922563.html
Copyright © 2011-2022 走看看