<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