.NET 线程学习笔记二

  

互斥锁:

    //互斥锁是一个互斥的同步对象,这意味着在同一个时间有且仅有一个线程可以获取它。互斥锁适用于下列情况:

    //一个共享资源每次只能被一个线程使用。例如:考虑一个由多个进程共享的日志文件,任意时刻只能有一个进程对
    //该文件执行写入操作。互斥锁是解决此类问题的最佳同步工具。
    //互斥锁由System.Threading.Mutex类支持。该类有多个构造函数,其中最常用的两个是:
    //publi Mutex()
    //publi Mutex(bool owned)
    //第一个版本创建一个处于未获取状态的互斥锁。
    //在第二个版本中,如果owned为true,互斥锁的初始状态就是被主调线程所获取,否则处于未获取状态。
    //要获取一个互斥锁,应当调用互斥锁上的WaitOne()方法。该方法继承于System.Threading.WaitHandle
    //下面是它的最简单形式:
    //public bool WaitOne();
    //它将处于等待状态知道所调用的互斥锁可以被获取。因此该方法将阻塞主线程直到指定的互斥锁可用。该方法总是返回true.
    //如果代码不再需要拥有互斥锁,可以调用下面的ReleaseMutex()方法来释放它:
    //public void ReleaseMutex();
    //在互斥锁上调用该方法将使得互斥锁被释放,从而允许该互斥锁被另一个线程所获取。
    //要使用互斥锁来同步对共享资源的访问,需要使用WaitOne()和ReleaseMutex如下面的代码所示。

    //Mutex myMtx = new Mutex();
    //myMtx.WaitOne();
    //myMtx.ReleaseMutex();

    //在调用WaitOne()方法是,线程的执行将挂起直到获取互斥锁。在调用ReleaseMutex方法时,互斥锁将被释放,从而另一个线程可以获取它。
    //通过这种方法,共享资源可以被限制为每次只允许一个线程访问。

  
public class ShardRes
    {
        public static int Count = 0;
        public static Mutex Mtx = new Mutex();
    }

    class IncThread
    {
        int num;
        public Thread Thrd;
        public IncThread(string name, int n)
        {
            Thrd = new Thread(new ThreadStart(this.Run));
            num = n;
            Thrd.Name = name;
            Thrd.Start();
        }
        void Run()
        {
            Console.WriteLine(Thrd.Name + " is waiting for the mutex");
            ShardRes.Mtx.WaitOne();
            Console.WriteLine(Thrd.Name + " acquires the mutex.");
            do
            {
                Thread.Sleep(500);
                ShardRes.Count++;
                Console.WriteLine("In " + Thrd.Name + ",ShardRes.Count is" + ShardRes.Count);
                num--;
            }
            while (num > 0);
            Console.WriteLine(Thrd.Name + " releases the mutex.");
            ShardRes.Mtx.ReleaseMutex();
        }
    }

    public class DecThread
    {
        int num;
        public Thread Thrd;
        public DecThread(string name, int n)
        {
            Thrd = new Thread(new ThreadStart(this.Run));
            num = n;
            Thrd.Name = name;
            Thrd.Start();
        }

        public void Run()
        {
            Console.WriteLine(Thrd.Name + " is waiting for the mutex");

            ShardRes.Mtx.WaitOne();

            do
            {

                Thread.Sleep(500);
                ShardRes.Count--;
                Console.WriteLine("In " + Thrd.Name + ",SharedRes.count is " + ShardRes.Count);
                num--;
            } while (num > 0);

            Console.WriteLine(Thrd.Name + " releases the mutex.");

            ShardRes.Mtx.ReleaseMutex();
        }

    }

    class ThreadFive
    {
        public static void Main(string[] arg)
        {
            Console.WriteLine("ok");
            IncThread mt1 = new IncThread("Increment Thread", 5);
            Thread.Sleep(1);
            DecThread mt2 = new DecThread("Decrement Thread", 5);
            mt1.Thrd.Join();
            mt2.Thrd.Join();
            Console.Read();
        }
    }

信号量:

 //信号量类似于互斥锁,但它可以允许多个线程同时访问一个共享资源。因此在同步一个资源集合的时候,信号量就显得非常有用。
    //信号量通过一个计数器来控制对共享资源的访问。如果计数器大于0,那么就iu允许访问。如果计数器等于0,就拒绝访问。计数
    //器累计的是“许可证”的个数。因此,为了访问某个资源,线程将阻塞直到得到一个许可证。

    //信号量特别使用于下列情况:一个由“组(group)”或者"池(pool)"构成的共享资源。例如一个网络连接的集合,其中每一个连接
    //都可以用于通信,这就是一个资源池。需要网络连接的线程并不关心它获取的是哪一个网络连接。在这种情况下,信号量提供了
    //一种方便的机制来管理对连接的访问。
    //信号量是由System.Threading.Semaphore实现的。它有多个构造函数,最简单形式为:
    //public Semaphore(int initial,int max)
    //其中,initial指定了信号量许可证计数器的初始值,它指定可用的许可证数目。计数器的最大值在max中传递。max地表了信号量
    //最多拥有的许可证数目.initial的值指定了初始情况下有多少个许可证可用。


    //获取信号量使用  WaitOne()
    //不再需要使用信号量使用Release()方法释放。

    //注意:
    //线程在调用Release()之前可以多次调用WaitOne().但是,在释放许可证之前,WaitOne()的调用次数必须和Release()的调用次数一致。
    //或者,也可以调用Release(int)形式,传入WaitOne()的调用次数。

    class ThreadSix
    {
        public Thread Thr;

        static Semaphore sem = new Semaphore(2, 2);

        public ThreadSix(string name)
        {
            Thr = new Thread(this.Run);
            Thr.Name = name;
            Thr.Start();
        }

        public void Run()
        {
            Console.WriteLine(Thr.Name + " is waiting for permit");

            sem.WaitOne();

            Console.WriteLine(Thr.Name + " is acquires for permit");

            for (char ch = 'A'; ch < 'D'; ch++)
            {
                Console.WriteLine(Thr.Name + " : " + ch + " ");
                Thread.Sleep(500);
            }

            Console.WriteLine(Thr.Name + " releases a permit.");

            sem.Release();
        }
    }

    public class SemaphoreDemo
    {
        static void Main(string[] arg)
        {
            ThreadSix t1 = new ThreadSix("one");
            ThreadSix t2 = new ThreadSix("two");
            ThreadSix t3 = new ThreadSix("three");

            t1.Thr.Join();
            t2.Thr.Join();
            t3.Thr.Join();

            Console.Read();
        }
    }

  //使用事件实现同步。
    //同步事件有两种类型:ManualResetEvent(手工重置) AutoResetEvent(自动重置)
    //事件处理非常简单。对于ManualResetEvent,其处理过程处理如下:等待某个事件
    //的线程简单的代表该事件的事件对象上调用WaitOne();如果事件对象处于已发出
    //信号状态,WaitOne将立即返回。它将挂起主调线程直到事件发出信号。在另一个线程执行事件之后,该线程通过调用
    //Set()来把事件对象置于已发出信号状态,对WaitOne()的调用将返回,并且第一个线程恢复执行。
    //调用Reset()将该事件重置为未发出信号状态。
    public class ThreadSeven
    {
        public Thread Thrd;
        ManualResetEvent mre;

        public ThreadSeven(string name, ManualResetEvent evt)
        {
            Thrd = new Thread(this.Run);
            Thrd.Name = name;
            mre = evt;
            Thrd.Start();
        }
        public void Run()
        {
            Console.WriteLine("Inside thread " + Thrd.Name);
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine(Thrd.Name);
                Thread.Sleep(500);
            }

            Console.WriteLine(Thrd.Name + " Done!");

           mre.Set();
        }
    }

    class ManualEventDemo
    {
        static void Main()
        {
            ManualResetEvent mre = new ManualResetEvent(false);

            ThreadSeven mt1 = new ThreadSeven("Event Thread 1", mre);

            Console.WriteLine("Main thread is waiting first event.");

            mre.WaitOne();
          
            Console.WriteLine("Main thread received first event.");

            mre.Reset();

            mt1 = new ThreadSeven("Event Thread 2", mre);

            mre.WaitOne();

            Console.WriteLine("Main Thread received second event.");

            Console.Read();
        }
    }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值