【多线程-线程同步】

来源:互联网 发布:528雾化器做丝数据 编辑:程序博客网 时间:2024/06/06 00:58

线程同步:协调多个线程间的并发操作,以获得符合预期的,确定的执行结果,消除多线程应用程序的不确定性.

使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取锁,释放锁。即锁机制;可以协调线程的访问顺序,即某一资源只能先由线程A访问,再由线程B进行访问。

    class Program    {        private static Thread subthread ;        private static int i;        static void Main(string[] args)        {            subthread = new Thread(new ThreadStart(GetShow));            subthread.Start();   //开启线程            GetShow();            //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");        }        static void GetShow()        {            Console.WriteLine(i);            i++;            //Console.WriteLine(i);        }    }

上面的代码执行时候,出现了两个线程同时访问同一个资源,向控制台输出后去执行i++操作,这样两个线程进来那一时间,i的值没有发生改变依旧是0,但执行i++后的值发生了改变,注释掉下面的输出运行程序发现:先输出2后输出的是1,这也是线程的执行顺序不确定而造成的值的输出顺序有差异。


使用排他锁,通过Monitor进行资源保护

1.使用对象作为锁对象:

 class Program    {        private static Thread subthread ;        private static int i;        private static object obj = new object();        static void Main(string[] args)        {            Thread.CurrentThread.Name = "主";            subthread = new Thread(new ThreadStart(GetShow));            subthread.Name = "subject";            subthread.Start();   //开启线程            GetShow();            //Console.WriteLine("{0}后台线程", Thread.CurrentThread.Name+Thread.CurrentThread.IsBackground+",结束");        }        static void GetShow()        {            Monitor.Enter(obj);// 在指定对象上获取排他锁。            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);            i++;            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);            Monitor.Exit(obj); // 释放指定对象上的排他锁。        }    }


使用System.Type进行锁对象:

修改上面的方法:运行结果与上面一致。
 <span style="white-space:pre"></span>static void GetShow()        {            Monitor.Enter(typeof(Program));// 在指定对象上获取排他锁。            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);            i++;            Console.WriteLine(Thread.CurrentThread.Name+">>"+i);            Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。        }

使用lock加锁:

如果上面的Monitor.Exit(typeof(Program))前面代码出现异常的话,主线程在执行到异常出会抛出异常,可以通过:try catch finall进行处理:
            try            {                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                i++;                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                throw new Exception("asdasd");            }            catch            {            }            finally            {                Monitor.Exit(typeof(Program)); // 释放指定对象上的排他锁。            }
使用lock可以进行简化:实现效果和上面一样.
            lock (typeof(Program))            {                try                {                    Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                    i++;                    Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                    throw new Exception("asdasd");                }                catch { }            }

进行[MethodImpl(MethodImplOptions.Synchronized)]标记

创建线程的安全类型,可以使用[MethodImpl(MethodImplOptions.Synchronized)]进行标记:


        [MethodImpl(MethodImplOptions.Synchronized)]//进行标记        static void GetShow()        {            try            {                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                i++;                Console.WriteLine(Thread.CurrentThread.Name + ">>" + i);                throw new Exception("asdasd");            }            catch { }        }

使用Monitor协调线程的执行顺序:

    class Program    {        private static Thread subthread ;        static void Main(string[] args)        {            Program p=new Program ();            Thread.CurrentThread.Name = "主线程";            subthread = new Thread(new ThreadStart(p.GetShow));            subthread.Name = "子线程";            subthread.Start();   //开启线程            lock (typeof(Program))            {                Monitor.Wait(typeof(Program));   // 释放对象上的锁并阻止当前线程,直到它重新获取该锁。                Console.WriteLine(Thread.CurrentThread.Name + "开始执行其他逻辑");            }          }        void GetShow()        {            lock (typeof(Program))            {                Console.WriteLine(subthread.Name+"线程执行完毕");                Monitor.Pulse(typeof(Program));  //通知等待队列中的线程锁定对象状态的更改。            }        }    }



1 1
原创粉丝点击