学习笔记 – Jtro的技术分享:c#中的线程互斥

通过多线程,c#能够并行执行代码。每一个线程都有它独立的执行路径,所有的线程都能够访问共有的变量。下面的例子说明这个问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Threading.Tasks;

namespace ThresdScript
{
    class MainClass
    {
        static string str = "";
        static void Main(string[] args)
        {
            Thread t1 = new Thread(Add1);
            t1.Start();
            Thread t2 = new Thread(Add2);
            t2.Start();
            //等待一段时间
            Thread.Sleep(1000);
            Console.WriteLine( str );
            Console.ReadKey();
        }
        //线程1
        public static void Add1()
        {
            for (int i = 0; i < 20; i++)
            {
                Thread.Sleep(10);
                str += 'a';
            }
        }
        //线程2
        public static void Add2()
        {
            for (int i = 0; i < 20; i++)
            {
                for (int j = 0; j < 20; j++)
                {
                    Thread.Sleep(10);
                    str += 'b';
                }
            }
        }
    }
}

由于两个线程并行执行,字符串str时而被Add1操作,时而被Add2操作,所以打印如下结果:

线程互斥.png

为了避免线程竞争,可以通过加锁的方式(Lock)来处理,当2个线程争夺一个锁的时候,只能有一个线程有资格获取,另一个挂起等待。一直等到可用为止,这种情况,保证在同一时刻只有一个线程能进入临界区。程序改为下面的状态:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Threading.Tasks;

namespace ThresdScript
{
    class MainClass
    {
        static string str = "";
        static void Main(string[] args)
        {
            Thread t1 = new Thread(Add1);
            t1.Start();
            Thread t2 = new Thread(Add2);
            t2.Start();
            //等待一段时间
            Thread.Sleep(1000);
            Console.WriteLine( str );
            Console.ReadKey();
        }
        //线程1
        public static void Add1()
        {
            lock (str)
            {
                for (int i = 0; i < 20; i++)
                {
                    Thread.Sleep(10);
                    str += 'a';
                }
            }
        }
        //线程2
        public static void Add2()
        {
            lock (str)
            {
                for (int i = 0; i < 20; i++)
                {
                    Thread.Sleep(10);
                    str += 'b';
                }
            }
        }
    }
}

运行后的2种情况:

第一种.png

第二种.png

正文完