C#线程学习笔记六:线程同步--信号量和互斥体

时间:2021-10-22 00:29:18

本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Mutex_And_Semaphore.html,记录一下学习过程以备后续查用。

    一、信号量(Semaphore)

信号量(Semaphore)是由内核对象维护的int变量。当信号量为0时,在信号量上等待的线程会堵塞;信号量大于0时,就解除堵塞。当在一个信号量上等待

的线程解除堵塞时,内核自动会将信号量的计数减1。在.NET下通过Semaphore类来实现信号量同步。

Semaphore类限制可同时访问某一资源或资源池的线程数。线程通过调用 WaitOne方法将信号量减1,并通过调用Release方法把信号量加1。

先说下构造函数:

public Semaphore(int initialCount,int maximumCount);通过两个参数来设置信号的初始计数和最大计数。

下面代码演示信号量同步的使用:

    class Program
{
//共享资源
public static int number = ;
//初始信号量计数为0,最大计数为10。
public static Semaphore semaphore = new Semaphore(, );
static void Main(string[] args)
{
#region 线程同步:使用信号量实现同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(SemaphoreMethod));
thread.Start(i);
} //每次增加2个信号量,即每次释放2个线程。
for (int j = ; j < ; j++)
{
Console.WriteLine("红灯转绿灯……");
semaphore.Release();
Thread.Sleep();
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore方法
/// </summary>
public static void SemaphoreMethod(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore.WaitOne();
Console.WriteLine("The current value of number is:{0}", ++number);
}
}

运行结果如下:

C#线程学习笔记六:线程同步--信号量和互斥体

与上一篇AutoResetEvent类似,信号量也可以实现跨进程间的线程同步。通过调用public Semaphore(int initialCount,int maximumCount,string name);

构造函数,传入一个信号量名来实现此功能。

下面代码演示跨进程间的线程同步:

第一个进程代码:

    class Program
{
//共享资源
public static int number = ; //初始信号量计数为0,最大计数为10。
public static Semaphore semaphore1 = new Semaphore(, , "Semaphore1");
public static Semaphore semaphore2 = new Semaphore(, , "Semaphore2"); static void Main(string[] args)
{
#region 线程同步:使用信号量实现跨进程之间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Semaphore1Method));
thread.Start(i);
} //为了有时间去启动另外一个进程
Thread.Sleep(); //每次增加2个信号量,即每次释放2个线程。
for (int j = ; j < ; j++)
{
Console.WriteLine("信号灯1红灯转绿灯……");
semaphore1.Release();
Console.WriteLine("信号灯2红灯转绿灯……");
semaphore2.Release();
Thread.Sleep();
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore1方法
/// </summary>
public static void Semaphore1Method(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore1.WaitOne();
Console.WriteLine("Semaphore1:The current value of number is:{0}", ++number);
}
}

第二个进程代码:

    class Program
{
//共享资源
public static int number = ;
//创建对象
public static Semaphore semaphore2 = new Semaphore(, , "Semaphore2"); static void Main(string[] args)
{
#region 通过信号量实现跨进程间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Semaphore2Method));
thread.Start(i);
}
Console.Read();
#endregion
} /// <summary>
/// Semaphore2方法
/// </summary>
public static void Semaphore2Method(object parameter)
{
while ((int)parameter != number)
{
Thread.Sleep();
}
//信号量计数减1
semaphore2.WaitOne();
Console.WriteLine("Semaphore2:The current value of number is:{0}", ++number);
}
}

运行结果如下:

C#线程学习笔记六:线程同步--信号量和互斥体

从结果可以看出,第一个进程的semaphore2.Release(2);信号发出后,第二个进程可以收到并释放线程。

二、互斥体(Mutex)

Mutex对象是一个同步基元,当某一个线程占用Mutex对象时,其他也需要占用Mutex的线程将处于挂起状态。

下面代码演示互斥体同步的使用:

    class Program
{
//共享资源
public static int number = ;
//互斥体
public static Mutex mutex = new Mutex(); static void Main(string[] args)
{
#region 线程同步:使用互斥体实现同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(MutexMethod);
thread.Start();
} Console.Read();
#endregion
} /// <summary>
/// Mutex方法
/// </summary>
public static void MutexMethod(object parameter)
{
mutex.WaitOne();
Thread.Sleep();
Console.WriteLine("The current value of number is:{0}", ++number);
mutex.ReleaseMutex();
}
}

运行结果如下:

C#线程学习笔记六:线程同步--信号量和互斥体

下面代码演示跨进程间的线程同步:

第一个进程代码:

    class Program
{
//共享资源
public static int number = ; //互斥体
public static Mutex mutex1 = new Mutex(false, "Mutex1");
public static Mutex mutex2 = new Mutex(false, "Mutex2"); static void Main(string[] args)
{
#region 线程同步:使用互斥体实现跨进程之间的线程同步
mutex1.WaitOne();
mutex2.WaitOne();
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Mutex1Method));
thread.Start(i);
} //为了有时间去启动另外一个进程
Thread.Sleep();
mutex1.ReleaseMutex();
mutex2.ReleaseMutex();
Console.Read();
#endregion
} /// <summary>
/// Mutex1方法
/// </summary>
public static void Mutex1Method(object parameter)
{
mutex1.WaitOne();
Thread.Sleep();
Console.WriteLine("Mutex1:The current value of number is:{0}", ++number);
mutex1.ReleaseMutex();
}
}

第二个进程代码:

    class Program
{
//共享资源
public static int number = ;
//创建对象
public static Mutex mutex2 = new Mutex(false, "Mutex2"); static void Main(string[] args)
{
#region 通过互斥体实现跨进程之间的线程同步
for (int i = ; i < ; i++)
{
Thread thread = new Thread(new ParameterizedThreadStart(Mutex2Method));
thread.Start(i);
}
Console.Read();
#endregion
} /// <summary>
/// Mutex2方法
/// </summary>
public static void Mutex2Method(object parameter)
{
mutex2.WaitOne();
Thread.Sleep();
Console.WriteLine("Mutex2:The current value of number is:{0}", ++number);
mutex2.ReleaseMutex();
}
}

运行结果如下:

C#线程学习笔记六:线程同步--信号量和互斥体

从结果可以看出,第一个进程的mutex2.ReleaseMutex();信号发出后,第二个进程可以收到并释放线程。