多线程实战(一) 线程基础

线程的好处,我想都不必多说,博客园太多了;但个人对线程了解还比较基础,决定把学习线程记录下来(有一些例子来之博客园):

创建线程

暂停线程

等待线程

线程传参数

lock

Monitor

创建线程

Thread t = new Thread(PrintNumbers);//线程创建
t.Start();//开始线程
PrintNumbers();
static void PrintNumbers() { Console.WriteLine("Starting..."); for (int i = 1; i < 10; i++) { Console.WriteLine(i); } }

暂停线程

sleep暂停线程;

Thread t = new Thread(PrintNumbersWithDelay);
            t.Start();


static void PrintNumbersWithDelay()
        {
            Console.WriteLine("Starting...");
            for (int i = 1; i < 10; i++)
            {
                Thread.Sleep(2000);
                Console.WriteLine(string.Format("顺序{0},时间:{1}", i, DateTime.Now));
            }
        }

sleep(2000);每隔2秒输出一次;

等待线程

  Thread t = new Thread(Run);

        t.Start();

        //Join相当于把Run方法内嵌如此
        t.Join();

        //该死的t.Join(),害的我主线程必须在你执行完后才能执行。
        Console.WriteLine("我是主线程:" + Thread.CurrentThread.GetHashCode());
    }

    static void Run()
    {
        //等待5s
        Thread.Sleep(5000);

        Console.WriteLine("我是线程:" + Thread.CurrentThread.GetHashCode());
    }

线程传参数

 var threadOne = new Thread(One);
            threadOne.Start("one");
            threadOne.Join();
            var threadTwo = new Thread(() => One("two"));
            threadTwo.Start();
            threadTwo.Join();
            var value = "three";
            var threadThree = new Thread(() => One(value));
            value = "four";
            var threadFour = new Thread(() => One(value));
            threadThree.Start();
            threadFour.Start();


static void One(object obj)
        {
            Console.WriteLine(obj);
        }

在启动线程3,4时,变量value的值变成four,最后打印出four

lock

Console.WriteLine("不规则统计");
            var c = new Counter();
            var t1 = new Thread(() => TestCounter(c));
            var t2 = new Thread(() => TestCounter(c));
            var t3 = new Thread(() => TestCounter(c));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("总计: {0}",c.Count);
            Console.WriteLine("--------------------------");
            Console.WriteLine("正确统计");
            var c1 = new CounterWithLock();
            t1 = new Thread(() => TestCounter(c1));
            t2 = new Thread(() => TestCounter(c1));
            t3 = new Thread(() => TestCounter(c1));
            t1.Start();
            t2.Start();
            t3.Start();
            t1.Join();
            t2.Join();
            t3.Join();
            Console.WriteLine("总计: {0}", c1.Count);

static void TestCounter(CounterBase c)
        {
            for (int i = 0; i < 100000; i++)
            {
                c.Increment();
                c.Decrement();
            }
        }

        class Counter : CounterBase
        {
            public int Count { get; private set; }

            public override void Increment()
            {
                Count++;
            }

            public override void Decrement()
            {
                Count--;
            }
        }

        class CounterWithLock : CounterBase
        {
            private readonly object _syncRoot = new Object();

            public int Count { get; private set; }

            public override void Increment()
            {
                lock (_syncRoot)
                {
                    Count++;
                }
            }

            public override void Decrement()
            {
                lock (_syncRoot)
                {
                    Count--;
                }
            }
        }

        abstract class CounterBase
        {
            public abstract void Increment();

            public abstract void Decrement();
        }

加了锁和不加锁统计的结果完全不一样

Monitor

同步访问对象机制;在锁定的临界区中只允许让一个线程访问,其他线程排队等待。

1:Monitor.Enter和Monitor.Exit

 for (int i = 0; i < 10; i++)
            {
                Thread t = new Thread(Run);

                t.Start();
            }

//资源
        static object obj = new object();

        static int count = 0;

        static void Run()
        {
            Thread.Sleep(10);

            //进入临界区
            Monitor.Enter(obj);

            Console.WriteLine("当前数字:{0}", ++count);

            //退出临界区
            Monitor.Exit(obj);
        }

2:Monitor.Wait和Monitor.Pulse

 Wait: 暂时的释放资源锁,然后该线程进入”等待队列“中,那么自然别的线程就能获取到资源锁。

 Pulse:  唤醒“等待队列”中的线程,那么当时被Wait的线程就重新获取到了锁。

 public class Program
    {
        public static void Main(string[] args)
        {
            LockObj obj = new LockObj();

            //注意,这里使用的是同一个资源对象obj
            Jack jack = new Jack(obj);
            John john = new John(obj);

            Thread t1 = new Thread(new ThreadStart(jack.Run));
            Thread t2 = new Thread(new ThreadStart(john.Run));

            t1.Start();
            t1.Name = "Jack";

            t2.Start();
            t2.Name = "John";

            Console.ReadLine();
        }
    }

    //锁定对象
    public class LockObj { }

    public class Jack
    {
        private LockObj obj;

        public Jack(LockObj obj)
        {
            this.obj = obj;
        }

        public void Run()
        {
            Monitor.Enter(this.obj);

            Console.WriteLine("{0}:我已进入茅厕。", Thread.CurrentThread.Name);

            Console.WriteLine("{0}:擦,太臭了,我还是撤!", Thread.CurrentThread.Name);

            //暂时的释放锁资源
            Monitor.Wait(this.obj);

            Console.WriteLine("{0}:兄弟说的对,我还是进去吧。", Thread.CurrentThread.Name);

            //唤醒等待队列中的线程
            Monitor.Pulse(this.obj);

            Console.WriteLine("{0}:拉完了,真舒服。", Thread.CurrentThread.Name);

            Monitor.Exit(this.obj);
        }
    }

    public class John
    {
        private LockObj obj;

        public John(LockObj obj)
        {
            this.obj = obj;
        }

        public void Run()
        {
            Monitor.Enter(this.obj);

            Console.WriteLine("{0}:直奔茅厕,兄弟,你还是进来吧,小心憋坏了!",
                               Thread.CurrentThread.Name);

            //唤醒等待队列中的线程
            Monitor.Pulse(this.obj);

            Console.WriteLine("{0}:哗啦啦....", Thread.CurrentThread.Name);

            //暂时的释放锁资源
            Monitor.Wait(this.obj);

            Console.WriteLine("{0}:拉完了,真舒服。", Thread.CurrentThread.Name);

            Monitor.Exit(this.obj);
        }
    }

原文地址:https://www.cnblogs.com/xchit/p/4777087.html