zoukankan      html  css  js  c++  java
  • 并行开发-线程同步机制

    线程同步技术

    争用条件:

    如果两个或多个线程访问相同的对象,并且对共享状态的访问没有同步,就会出现争用条件

    class StateObject
        {
            private int state = 5;
    
            public void ChangeState()
            {
                state++;
                if (state == 5)
                {
                    Console.WriteLine("value=5");
                }
                state = 5;
            }
        }
    class ThreadTest
        {
            static void Main(string[] args)
            {
                StateObject m = new StateObject();
                Thread t1 = new Thread(ChangeState);           
                t1.Start(m);           
                Console.ReadKey();
            }
    
            static void ChangeState(object o)
            {
                StateObject m = o as StateObject;
                while (true)
                {
                    m.ChangeState();
                }
            }
        }

    此时运行程序是没有输出的,因为StateObject类中state初始值是5,if条件不会进入,随后又将state从新初始化为5

    两个线程执行

    static void Main(string[] args)
            {
                StateObject m = new StateObject();
                Thread t1 = new Thread(ChangeState);
                Thread t2 = new Thread(ChangeState);
                t1.Start(m);
                t2.Start(m);
                Console.ReadKey();
            }

    此时会不停的打印"value=5",原因在于:一个线程在判断语句处时,另一个线程可能又将state的值改为了5,而导致输出合法

    死锁

    class Deadlock
    {
        static StateObject o1 = new StateObject();
        static StateObject o2 = new StateObject();
        public static void DeadlockA(object o)
        {
            lock (o1)
            {
                Console.WriteLine("我是线程{0},我锁定了对象o1", o);
                lock (o2)
                {
                    Console.WriteLine("我是线程{0},我锁定了对象o2", o);
                }
            }
        }
    
        public static void DeadlockB(object o)
        {
            lock (o2)
            {
                Console.WriteLine("我是线程{0},我锁定了对象o2", o);
                lock (o1)
                {
                    Console.WriteLine("我是线程{0},我锁定了对象o1", o);
                }
            }
        }
    }
     Thread t1 = new Thread(Deadlock.DeadlockA);
     Thread t2 = new Thread(Deadlock.DeadlockB);
            t1.Start("t1");
            t2.Start("t2");

    t1线程执行DeadlockA()方法顺序锁定o1和o2,t2线程执行DeadlockB()方法顺序锁定o2和o1,当前结果显示t1线程锁定了o1后,t2线程在t1线程锁定o1后抢占进来,锁定了o2,t2在等t1解锁,t1在等t2解锁,都处于挂起状态在等对方解锁,这就形成了死锁,线程将无限等待下去

    这个问题应该从一开始就设计好锁定顺序,也可以为锁定义超时时间来处理,保证“上锁”这个操作在一个线程上执行也是避免死锁的方法之一

    C#中有多个用于多线程的同步技术

    • lock语句
    • Interlocked类
    • Monitor类
    • SpinLock类
    • WaitHandle类
    • Mutex类
    • Semapphore类
    • Event类
    • Barrier类
    • ReaderWriteLockSlim类

    其中lock语句/Interlocked类/Monitor类可用于进程内存的同步,其它几个提供了多进程之间的线程同步

    Lock

    C#使用lock语句锁定在线程中共享的变量,如果一个线程锁定了变量,另一个线程就必须等待该锁定的解除

    static void ChangeState(object o)
            {
                StateObject m = o as StateObject;
                while (true)
                {
              //给变量m加锁 lock (m) { m.ChangeState(); } } }

    因为实例的对象也可以用于外部的同步访问,而且不能在类自身控制这种访问,所以应采用SyncRoot模式,创建私有对象,将这个对象用于lock语句

            private static object syncRoot= new object();
            static void ChangeState(object o)
            {
                StateObject m = o as StateObject;
                while (true)
                {
                    lock (aync)
                    {
                        m.ChangeState();
                    }
                }
            }

    需要注意:

    1:lock只能锁定对象,即引用类型,不能锁定值类型.

    2:lock不能锁定空值,因为null是不需要被释放的

    3:不能锁定string类型,虽然它也是引用类型的。因为字符串类型被CLR“暂留”,这意味着整个程序中任何给定字符串都只有一个实例,具有相同内容的字符串上放置了锁,就将锁定应用程序中该字符串的所有实例

    4:避免锁定public类型,如果该实例可以被公开访问,则 lock(this) 可能会有问题,因为不受控制的代码也可能会锁定该对象

  • 相关阅读:
    oracle 12C linux centos7.5 安装 12C
    FizzBuzz
    批量判断能否telnet登录
    统计所有机器的挂载情况
    ffmpeg windows vs library 下载地址
    需求文档测试
    接口测试分析
    chrome网页截图
    不要为了测试写一个新系统
    C# 判断是否为数字
  • 原文地址:https://www.cnblogs.com/GnailGnepGnaw/p/10658684.html
Copyright © 2011-2022 走看看