两种新建线程的简单方法以及懒汉模式中lock的重要性

来源:互联网 发布:java程序员到架构师 编辑:程序博客网 时间:2024/06/08 09:51

先扔代码吧。。。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;//Parallel类namespace ThreadDemo{    class Program    {        static void Main(string[] args)        {            ThreadDemo[] array = new ThreadDemo[10];            for (int i = 0; i < 10; i++)                //array[i] = new CreateOnlyOneThread();                array[i] = new CreateOnlyOneInvoke();            Parallel.ForEach(array, i => i.Start());            Console.ReadLine();        }    }    interface ThreadDemo    {        void Start();    }    class CreateOnlyOneThread : ThreadDemo    {        private Thread thread;        private delegate void CreateOnlyOneThreadMethod();        public void GetOnlyOne()        {            OnlyOne.GetOnlyOne();        }        public void Start()        {            CreateOnlyOneThreadMethod createOnlyOneThreadMethod = GetOnlyOne;            thread = new Thread(new ThreadStart(createOnlyOneThreadMethod));            thread.IsBackground = true;            thread.Start();        }    }    class CreateOnlyOneInvoke : ThreadDemo    {        IAsyncResult iar;        private delegate void CreateOnlyOneInvokeMothed();        public void GetOnlyOne()        {            OnlyOne.GetOnlyOne();        }        public void Start()        {            CreateOnlyOneInvokeMothed createOnlyOneInvokeMothed = GetOnlyOne;            iar = createOnlyOneInvokeMothed.BeginInvoke(null, null);        }    }    class OnlyOne    {        private static OnlyOne onlyone;        private static object obj= new object();        private OnlyOne()        {            Console.WriteLine("Create!");        }        public static OnlyOne GetOnlyOne()        {            if (onlyone==null)                lock(obj)                {                    if (onlyone==null)                        onlyone=new OnlyOne();                }            return onlyone;        }    }}

上面的代码中CreateOnlyOneThread类和CreateOnlyOneInvoke类分别是两种新建线程的方法,感觉都挺好上手的,但是他们都有一个共同的特点就是要用委托。

但是效果上有点不同

BeginInvoke方法创造出来的子线程可以理解为 他的IsBackGround为True,也就是说如果主线程(这里面是Main)结束的话,不管子线程有没有执行完毕都会退出。

而Thread,Start()的线程是可以调的,如果IsBackGround为false,那么即使主线程结束,仍然会等待子线程结束。

但是如果做得不是控制台而是Windows程序的话,这种情况直接alt+F4,打开任务管理器发现进程仍然还在!


然后再说下lock的事。。。

一般都是用lock(this)的。。。但是由于是静态方法,所以只能新建一个静态的object对象。

第一层是判断当前是否已经创建OnlyOne的对象,如果没有创建,那么向下执行。

然后问题来了,既然已经锁住了,那么还加一层判断干什么?这正是多线程麻烦的地方。。。

如果一个线程,我们大概可以在脑中模拟出程序执行的过程,但是如果是多线程的话,就不一样了。。。因为即使是只添加一个线程,程序运行的结果就已经不能预测得到的了。所以一般调多线程的程序都不用debug。。。

回到主题,打个比方,有一个400米赛跑比赛,比赛规定:1、如果有人完成比赛,那么设在100米检查点(也就是第一个 if (onlyOne==null) )就禁止选手通过(就是对象已经穿件完毕,不用在创建了)。2、如果有人已经通过了200米检查点,那么其他选手要在200检查点处等待,直到那个通过200,米检查点的选手完成比赛,才允许下一个选手通过200米检查点(也就是lock(obj){}的那块)。

如果是普通的单线程的话,就是第一个人先跑,跑到终点之后第二个再跑。这样按照规则,因为第一个人已经完成了比赛,所以第二个,第三个,以及他们后面的都无法通过100米的检查点。但是现在不同,现在是所有人一起跑,所以当有人第一个通过终点前肯定也有人已经也跑过了100米的检查点,这个时候大家来到了200米的检查点,由于先前通过200米检查点的人没有通过终点,所以大家(众线程)只好等待(这个也就是lock的作用),直到那个人通过重点(创建完对象,解锁),才会有下一个人通过200米检查点。这个时候第二个 if (onlyOne==null) 的作用就体现出来了,如果之前没有创建,那么onlyOne为null,创建对象,如果不为null,说明已经创建完,不再创建。这样才算是只创建了一个对象。

所以无论是写什么样的代码,一旦涉及多线程,一定要多运行几次,看看会不会出错误,因为多线程的随机化真的很难预测。

0 0
原创粉丝点击