天天看点

c# 多线程学习笔记(二)互斥,同步

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。</span>
           

同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源,如“第一类读写者模型”。

通过以下题目来说明互斥与同步:

程序描述:

主线程启动10个子线程并将表示子线程序号的变量地址作为参数传递给子线程。子线程接收参数 ->sleep(50) -> 全局变量++ ->sleep(0) -> 输出参数和全局变量。

要求:

1.子线程输出的线程序号不能重复。

2.全局变量的输出必须递增。

分析:

1.主线程创建子线程并传入一个指向变量地址的指针作参数,由于线程启动须要花费一定的时间,所以在子线程根据这个指针访问并保存数据前,主线程应等待子线程保存完毕后才能改动该参数并启动下一个线程。这涉及到主线程与子线程之间的同步。

2.子线程之间会互斥的改动和输出全局变量。要求全局变量的输出必须递增。这涉及到各子线程间的互斥。

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

namespace SyncAndMutex
{
  
    class Program
    {
        static int mResource =0;
        static int threadcount = 10;
        static ManualResetEvent resetevent = new ManualResetEvent(false);
        static Object mCriticalSectionObj = new Object();
        static void Main(string[] args)
        {
            Pointer pt = new Pointer(0);
            for (int i = 0; i < threadcount; ++i)
            {
                Thread td = new Thread(ThreadTask);
                pt.PointValue = i;
                td.Start(pt);
                resetevent.WaitOne();
                resetevent.Reset();// if use the autoresetevent,it's unnecesary to call the reset()
            }
        } 

        static void ThreadTask(object threadorderid)
        {
            int id = ((Pointer)threadorderid).PointValue;//copy the value
            resetevent.Set();

            Monitor.Enter(mCriticalSectionObj);
            Thread.Sleep(50);
            mResource += 1;
            Thread.Sleep(0);
            Console.WriteLine("The Thread Order ID is " + id + " The Resource is " + mResource);
            Monitor.Exit(mCriticalSectionObj);
        }
    }

    class Pointer
    {
        public Pointer(int pointervalue)
        {
            mv = pointervalue;
        }

        int mv = -1;

        public int PointValue
        {
            get { return mv; }
            set { mv = value; }
        }
    }
}
           

在代码中,为了体现出同步,所以专门构建class Pointer 作为参数,注意在此,如果将Int 型的i直接作为实参,那么每次实参到形参object都会重新构造对象,这样对于每一个子线程启动线程函数,使用每一份object都是新的独立的,从而将不需要同步操作。

 参考:

http://blog.csdn.net/morewindows/article/details/7442333

http://blog.csdn.net/MoreWindows/article/details/7442639

http://blog.csdn.net/MoreWindows/article/details/7470936

继续阅读