我正在接近C Windows编程,特别是线程,并发和同步。
为了实验,我正在编写一个接受N个参数的C程序
每个参数都指示文件系统目录树的路径,程序必须比较所有目录的内容,以确定所有目录是否具有相同的内容。
主要是"阅读"每个参数的线程,而单个"比较" thread比较找到的所有条目的名称。对于找到的每个文件/目录,"阅读"线程通过激活"比较"来同步自己。线程。
我用Semaphore
个对象编写了程序,现在我尝试使用Event
个对象。
我们的想法是使用N Events auto-reset
和single Event manual-reset
。
N"阅读&#34>使用N个事件。线程表示"比较" WaitForMultipleObjects
时间INFINITE
的线程。当所有信号都可用时,它开始比较条目,然后为手动重置对象执行SetEvent()
。
"阅读"线程等待此设置,然后重置事件并继续使用下一个条目。
N个阅读主题的一些代码:
void ReadingTraverseDirectory(LPTSTR StartPathName, DWORD i) {
//variables and some work
do {
//take the next entry and put it in current_entry;
gtParams[it].entry = current_entry; //global var for comparison
SetEvent(glphReadingEvent[i]); //signal the comparison thread
WaitForSingleObject(ghComparisonEvent, INFINITE); //wait signal to restart working
ResetEvent(ghComparisonEvent); //reset the event
if (current_entry == TYPE_DIR) {
ReadingTraverseDirectory(current_entry, i); //recur to explor the next dir
}
} while (FindNextFile(SearchHandle, &FindData)); //while there are still entries
//
return;
}
比较线程的一些代码:
DWORD WINAPI CompareThread(LPVOID arg) {
while (entries are equal){
WaitForMultipleObjects(N, glphReadingEvent, TRUE, 1000);
for (r = 0; r < nworkers - 1; r++){
if (_tcscmp(entries) != 0){
//entries are different. exit and close.
}
}
SetEvent(ghComparisonEvent);
}
}
问题:
有时候,一个阅读线程能够在不尊重与其他线程同步的情况下工作。如果我在比较线程的等待和设置之间放置printf()
或Sleep(1)
,则程序运行良好。
我的意见:
我认为手动重置事件对于这种(屏障)同步是不安全的
读取线程在ResetEvent()
中可能太快,如果调度程序减慢了其他线程的速度,则其中一些线程可能会被阻塞,而执行重置的线程可能会继续其工作。
但是,如果是这种情况,比较线程应该在WaitingForMultipleObjects
上阻塞自身导致死锁...实际上没有死锁但是1个线程能够相对于其他线程循环更多次。
/>
我想要了解的是为什么简单的睡眠(1)可以解决问题。是调度还是错误实现同步?
谢谢。