码迷,mamicode.com
首页 > 编程语言 > 详细

【多线程-线程同步】

时间:2016-05-20 10:05:37      阅读:201      评论:0      收藏:0      [点我收藏+]

标签:

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

使用线程的同步:可以保护资源同时只能由一个线程访问,一般采取的措施是获取锁,释放锁。即锁机制;可以协调线程的访问顺序,即某一资源只能先由线程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));  //通知等待队列中的线程锁定对象状态的更改。
            }
        }
    }
技术分享


【多线程-线程同步】

标签:

原文地址:http://blog.csdn.net/heyangyi_19940703/article/details/51455193

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!