• 多线程小结(三)线程同步总结


    对线程同步做一个总结,

    一般来说,线程同步比较让人纠结的地方在于它是许多线程共用一段代码的,而且什么时候谁用谁不用,也基本是不可控制不可预料的,那么对于它们可能会同时访问并更改的数据,就需要加锁了。加锁就是将一段代码变为临界区  ——  一段在同一时候只被一个线程进入/执行的代码,加锁的方式一般有两种,Lock关键字

    C#提供lock关键字实现临界区,MSDN里给出的用法:

    Object thisLock= new Object();

    lock (thisLock)
    {

       // Critical code section

    此方法的难点是如何选择锁的对象,比如写日志类,如果是静态对象锁自身,那么即使是不冲突的操作,也会互斥,白白浪费了cpu的时间片(像是你所在的a车道可以走了,但非要等到b车道空闲了,你才开始走a车道)

    普通的需要实例化的类也要注意,如果是锁this,那么一旦这个对象有多个实例,那么多个实例的操作就变成不互斥了,因为它们锁住的不是同一个thisLock同时也可以在外部声明一个object,将引用传入临界区,让临界区锁住这个对象,但这种方式比较灵活,但使用起来也需要很小心的维护这个引用。

    还有种方法是使用 Monitor

    System.Objectobj = (System.Object)x;
    System.Threading.Monitor.Enter(obj);
    try
    {
      DoSomething();
    }
    finally
    {
      System.Threading.Monitor.Exit(obj);
    }

    Enter和exit 望文生义,就是进入临界区和离开临界区,其实和lock使用起来没什么区别,只是多了个finally,在这里你可以多做一些事情,类似于using的自动dispose和寻常的try  finally dispose的区别。不过monitor还有一些其他方法,如Wait和Pulse,可以起到暂停线程和通知拥有锁对象的线程的作用,但我不明白的是,为什么这两个也是静态方法。对于它的运行机制,还不太了解。

    还有mutex也可以完成同步,但是用法比较复杂,它的特性是可以在进程中同步,所以线程同步一般不会用它。

     System .Object 
       System .MarshalByRefObject 
         System.Threading .WaitHandle 
           System.Threading .Mutex 

    也可以合理利用volatile 关键字,

    msdnvolatile 关键字指示一个字段可以由多个同时执行的线程修改。 声明为 volatile 的字段不受编译器优化(假定由单个线程访问)的限制。 这样可以确保该字段在任何时间呈现的都是最新的值。

    volatile 修饰符通常用于由多个线程访问但不使用 lock 语句对访问进行序 列化的字段。

    volatile 关键字可应用于以下类型的字段:

    • 引用类型。

    • 指针类型(在不安全的上下文中)。请注意,虽然指针本身可以是可变的,但是它指向的对象不能是可变的。换句话说,您无法声明“指向可变对象的指针”。

    • 整型,如 sbyte、byte、short、ushort、int、uint、char、float 和 bool。

    • 具有整数基类型的枚举类型。

    • 已知为引用类型的泛型类型参数。

    可变关键字仅可应用于类或结构字段。不能将局部变量声明为 volatile。


    线程同步易出错的地方是,全局变量和静态变量,这个必须非常小心。

    前面也提到了,线程是共享资源的,所以每一个线程都是访问的同一个全局变量和静态变量(局部变量无此隐患)。

    一个很简单的示例,

     int 全局变量 i

    1 {    if(i%2==1)

    2 {sysout(i +"是单数")}

    3 else { i 是双数}

    4 i++   ;

    }  这段代码在多个线程里面被并发执行,查看输出,会发现很多错误,因为1执行完毕,进入2或3,但还未执行,这时其他线程可能执行了4,所以i被++了。



  • 相关阅读:
    poj 1700 Crossing River 过河问题。贪心
    Alice's Print Service
    POI 2000 ------Stripes
    Uva 1378
    hdu 3068 最长回文
    bnu Game 博弈。
    链栈的C语言实现
    链栈的C语言实现
    顺序栈C语言实现
    顺序栈C语言实现
  • 原文地址:https://www.cnblogs.com/suijing/p/3379392.html
Copyright © 2020-2023  润新知