0

我目前有一个程序一次运行大约 20 个线程。我对多线程相当陌生,所以我对正确的数据保护有点困惑。

目前,我的线程使用事件作为数据锁定和解锁。我选择在关键部分使用它,因为大多数数据仅在两个或三个线程之间共享,因此通过停止所有 20 个线程来防止单个线程读取而一个线程写入似乎很浪费。我使用 Event over Mutex 仅仅是因为我无法(轻松地)找到一个清楚地解释 Mutex 如何工作以及如何实现的源。

我正在为我的多线程使用 Win32 API。在我当前的设置中,我使用事件来锁定数据,因此我的事件将类似于“DataUnlock” 当未设置时,我知道正在处理数据。设置后,我知道可以处理数据。所以我的临时数据锁看起来像这样。

WaitForSingleObject( DataUnlock,INFINITE );    //Wait until the Data is free  
ResetEvent(DataUnlock);                     //Signal that the data is being worked on   
...work on Data...    
SetEvent(DataUnlock);                       //Signal that the data is free to use

我的第一个问题是:当只有两个线程访问数据时,这是否与使用 Mutex 一样好(高效)?

第二:如果有两个以上的线程等待访问数据,是否有可能在数据被释放时都被触发(在一个到达 ResetEvent 之前两者都会通过等待)?如果是这样,互斥锁会不会有同样的问题?

最后:如果互斥锁更可取,我将如何实现一个(非常感谢链接或解释)?

谢谢!

4

1 回答 1

1

我不认为事件方法是保护数据的最佳方式。

查看互斥对象使用互斥对象以了解互斥锁。

  1. 您的一个线程必须创建一个互斥锁。CreateMutex 函数返回互斥对象的句柄。您可以将句柄作为参数传递给处理数据的线程。
  2. 使用WaitForSingleObject 函数等待互斥体,然后处理您的数据。通过调用ReleaseMutex 函数来释放互斥锁。当互斥锁被释放时,下一个等待函数将获得互斥锁。
  3. 如果要由多个进程的线程访问数据,则必须使用命名互斥锁。

查看临界区对象以了解临界区同步。

如果你想拥有

  1. 必须通过调用InitializeCriticalSection 函数来创建临界区。
  2. 在处理数据之前,请在所有位置使用EnterCriticalSection 函数。
  3. LeaveCriticalSection函数释放临界区释放对象。完成数据后使用此调用。

临界区只能由拥有线程进入。一旦一个线程获得了临界区对象,其他线程就无法访问您的数据。其他线程将在调用EnterCriticalSection(). 然而,拥有临界区的线程可以EnterCriticalSection()多次连续调用。每次调用应注意调用LeaveCriticalSection()一次。EnterCriticalSection()

您的示例将让所有等待事件的线程处理您的数据。如果发生了任何类型的处理,您只能通过数据本身知道。这取决于您,如何确定已完成的工作以及仍需完成的工作。如果您有许多线程在等待您的事件,则无法确定获取访问权限的顺序。


我建议使用临界区对象。它重量轻且相对易于使用。有关如何使用临界区对象的示例,请参阅使用临界区对象

于 2012-07-28T17:24:04.143 回答