如何控制好多个线程相互之间的联系,不产生冲突和重复,这需要用到互斥对象,即:System.Threading 命名空间中的 Mutex 类。
我们可以把Mutex看作一个出租车,乘客看作线程。乘客首先等车,然后上车,最后下车。当一个乘客在车上时,其他乘客就只有等他下车以后才可以上车。而线程与Mutex对象的关系也正是如此,线程使用Mutex.WaitOne()方法等待Mutex对象被释放,如果它等待的Mutex对象被释放了,它就自动拥有这个对象,直到它调用Mutex.ReleaseMutex()方法释放这个对象,而在此期间,其他想要获取这个Mutex对象的线程都只有等待。
下面这个例子使用了Mutex对象来同步四个线程,主线程等待四个线程的结束,而这四个线程的运行又是与两个Mutex对象相关联的。
其中还用到AutoResetEvent类的对象,可以把它理解为一个信号灯。这里用它的有信号状态来表示一个线程的结束。
// AutoResetEvent.Set()方法设置它为有信号状态
// AutoResetEvent.Reset()方法设置它为无信号状态
Mutex 类的程序示例:
using System;
using System.Threading;
namespace ThreadExample
{
public class MutexSample
{
static Mutex gM1;
static Mutex gM2;
const int ITERS = 100;
static AutoResetEvent Event1 = new AutoResetEvent(false);
static AutoResetEvent Event2 = new AutoResetEvent(false);
static AutoResetEvent Event3 = new AutoResetEvent(false);
static AutoResetEvent Event4 = new AutoResetEvent(false);
public static void Main(String[] args)
{
Console.WriteLine("Mutex Sample ");
//创建一个Mutex对象,并且命名为MyMutex
gM1 = new Mutex(true,"MyMutex");
//创建一个未命名的Mutex 对象.
gM2 = new Mutex(true);
Console.WriteLine(" - Main Owns gM1 and gM2");
AutoResetEvent[] evs = new AutoResetEvent[4];
evs[0] = Event1; //为后面的线程t1,t2,t3,t4定义AutoResetEvent对象
evs[1] = Event2;
evs[2] = Event3;
evs[3] = Event4;
MutexSample tm = new MutexSample( );
Thread t1 = new Thread(new ThreadStart(tm.t1Start));
Thread t2 = new Thread(new ThreadStart(tm.t2Start));
Thread t3 = new Thread(new ThreadStart(tm.t3Start));
Thread t4 = new Thread(new ThreadStart(tm.t4Start));
t1.Start( );// 使用Mutex.WaitAll()方法等待一个Mutex数组中的对象全部被释放
t2.Start( );// 使用Mutex.WaitOne()方法等待gM1的释放
t3.Start( );// 使用Mutex.WaitAny()方法等待一个Mutex数组中任意一个对象被释放
t4.Start( );// 使用Mutex.WaitOne()方法等待gM2的释放
Thread.Sleep(2000);
Console.WriteLine(" - Main releases gM1");
gM1.ReleaseMutex( ); //线程t2,t3结束条件满足
Thread.Sleep(1000);
Console.WriteLine(" - Main releases gM2");
gM2.ReleaseMutex( ); //线程t1,t4结束条件满足
//等待所有四个线程结束
WaitHandle.WaitAll(evs);
Console.WriteLine(" Mutex Sample");
Console.ReadLine();
}
public void t1Start( )
{
Console.WriteLine("t1Start started, Mutex.WaitAll(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1;//创建一个Mutex数组作为Mutex.WaitAll()方法的参数
gMs[1] = gM2;
Mutex.WaitAll(gMs);//等待gM1和gM2都被释放
Thread.Sleep(2000);
Console.WriteLine("t1Start finished, Mutex.WaitAll(Mutex[]) satisfied");
Event1.Set( ); //线程结束,将Event1设置为有信号状态
}
public void t2Start( )
{
Console.WriteLine("t2Start started, gM1.WaitOne( )");
gM1.WaitOne( );//等待gM1的释放
Console.WriteLine("t2Start finished, gM1.WaitOne( ) satisfied");
Event2.Set( );//线程结束,将Event2设置为有信号状态
}
public void t3Start( )
{
Console.WriteLine("t3Start started, Mutex.WaitAny(Mutex[])");
Mutex[] gMs = new Mutex[2];
gMs[0] = gM1;//创建一个Mutex数组作为Mutex.WaitAny()方法的参数
gMs[1] = gM2;
Mutex.WaitAny(gMs);//等待数组中任意一个Mutex对象被释放
Console.WriteLine("t3Start finished, Mutex.WaitAny(Mutex[])");
Event3.Set( );//线程结束,将Event3设置为有信号状态
}
public void t4Start( )
{
Console.WriteLine("t4Start started, gM2.WaitOne( )");
gM2.WaitOne( );//等待gM2被释放
Console.WriteLine("t4Start finished, gM2.WaitOne( )");
Event4.Set( );//线程结束,将Event4设置为有信号状态
}
}
}
程序的输出结果:
Mutex Sample
- Main Owns gM1 and gM2
t1Start started, Mutex.WaitAll(Mutex[])
t2Start started, gM1.WaitOne( )
t3Start started, Mutex.WaitAny(Mutex[])
t4Start started, gM2.WaitOne( )
- Main releases gM1
t2Start finished, gM1.WaitOne( ) satisfied
t3Start finished, Mutex.WaitAny(Mutex[])
- Main releases gM2
t1Start finished, Mutex.WaitAll(Mutex[]) satisfied
t4Start finished, gM2.WaitOne( )
Mutex Sample
从执行结果可以很清楚地看到,线程t2,t3的运行是以gM1的释放为条件的,而t4在gM2释放后开始执行,t1则在gM1和gM2都被释放了之后才执行。Main()函数最后,使用WaitHandle等待所有的AutoResetEvent对象的信号,这些对象的信号代表相应线程的结束
分享到:
相关推荐
在C++编程中,线程互斥对象是多线程编程中的关键概念,它用于确保同一时间只有一个线程可以访问特定的资源或执行特定的代码段。这有助于防止数据竞争和不一致的状态,从而保证程序的正确性。本文将详细探讨如何在C++...
互斥对象(Mutex)是一种有效的工具,用于实现不同进程间线程的同步。本文将深入探讨互斥对象的概念、工作原理以及如何在实践中应用它来保证资源的安全访问。 1. **互斥对象(Mutex)基础** 互斥对象是一种同步...
互斥对象(Mutex)是实现线程同步的一种常见机制,尤其在MFC(Microsoft Foundation Classes)库中有着广泛的应用。本文将详细探讨如何在MFC工程中使用Mutex来实现线程同步。 1. **互斥对象(Mutex)基础** - 互斥...
"易语言创建互斥对象禁止重复运行模块"是一个解决此类问题的解决方案,尤其适用于防止同一程序在同一台计算机上多次启动的情况。易语言,是一种面向对象的、中文编程语言,它的设计目标是降低编程的难度,让普通用户...
本文将深入探讨两种常见的同步原语——互斥对象锁(Mutex)和临界区(Critical Section),并对比它们的性能和适用场景。 首先,我们来了解什么是互斥对象锁。互斥锁是一种用于保护共享资源的同步机制,它确保同一...
线程互斥对象允许我们限制对共享资源的访问,防止多个线程同时访问同一资源,从而避免数据竞争和不一致状态。 1. **线程互斥对象(Mutex)**: 线程互斥对象是一种同步机制,当一个线程获得了Mutex的所有权后,...
这个压缩包文件"创建互斥对象禁止软件重复运行易语言模块源码-易语言.zip"(实际上是一个rar文件)提供了一个易语言(EasyLanguage)编写的模块,用于实现互斥对象的概念,从而防止同一软件的多个实例在同一台计算机...
本文将深入探讨如何在VC++环境下利用互斥对象(Mutex)来实现线程同步,以此避免竞态条件和数据不一致性的问题。 互斥对象是Windows API提供的一种同步机制,它允许一个线程在对共享资源进行访问时独占该资源,其他...
标题提到的"创建互斥对象禁止软件重复运行易语言模块源码"是解决一个特定问题的技术手段,即防止同一款软件在同一台计算机上多次开启,也就是所谓的“软件多开”。这种方式常用于单实例应用的实现,例如某些财务软件...
在这个“易语言源码创建互斥对象禁止重复运行模块源码.rar”压缩包中,包含了用易语言编写的一段程序,其主要目的是实现程序的互斥运行,确保同一时间只有一个实例在运行。 互斥对象,也称为互斥锁,是多线程编程中...
4个线程互斥类,代码例子,完整的工程,详细说明了4中互斥对象的作用,对学习多线程编程的朋友很有用处............
C 创建线程互斥对象的实例源码下载,声明线程函数,创建线程,程序睡眠,释放互斥对象,设置事件对象为无信号状态,生成控制台程序,仅供参考。
本资源主要讲解了如何在C#中使用互斥对象(Mutex)来管理多线程,确保线程安全。 互斥对象是.NET框架提供的一个同步原语,它用于保护共享资源免受并发访问的影响。当一个线程拥有互斥对象时,其他试图获取该对象的...
VC 使用MFC类创建互斥对象,通过这个小程序,你可以了解到声明线程函数、定义全局互斥对象、定义线程句柄、创建线程、程序睡眠、锁定互斥对象、变量自加、线程睡眠、释放互斥对象、线程正常退出等相关基础知识。
易语言创建互斥对象禁止重复运行模块源码.zip易语言项目例子源码下载易语言创建互斥对象禁止重复运行模块源码.zip易语言项目例子源码下载 1.合个人学习技术做项目参考 2.适合学生做毕业设计参考 3.适合小团队开发...
在Windows操作系统中,VC++(Visual C++)提供了多种线程同步机制,其中互斥对象(Mutex)是一种常用的手段。本实例将探讨如何在VC++环境下使用互斥对象实现线程同步。 互斥对象是Windows API提供的一种同步对象...
内容索引:VC/C++源码,其它分类,MFC,互斥 VC++ 使用MFC类创建互斥对象,通过这个小程序,你可以了解到声明线程函数、定义全局互斥对象、定义线程句柄、创建线程、程序睡眠、锁定互斥对象、变量自加、线程睡眠、释放...
在创建互斥对象时,我们会用到“创建互斥体”这条命令,这会生成一个全局唯一的标识符,代表了一个互斥对象。 一旦程序启动,它将尝试创建互斥对象。如果对象已经存在(意味着另一个实例已经在运行),那么创建就会...