Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 事件对象手动重置,线程同步错误_C_Windows_Multithreading_Events_Synchronization - Fatal编程技术网

C 事件对象手动重置,线程同步错误

C 事件对象手动重置,线程同步错误,c,windows,multithreading,events,synchronization,C,Windows,Multithreading,Events,Synchronization,我正在学习C Windows编程,特别是线程、并发和同步。 为了进行实验,我正在编写一个接受N个参数的C程序。 每个参数表示文件系统目录树的路径,程序必须比较所有目录的内容,以确定所有目录是否具有相同的内容。 main为每个参数运行一个“读取”线程,而单个“比较”线程则比较找到的所有条目的名称。对于找到的每个文件/目录,“读取”线程通过激活“比较”线程进行同步 我用信号量对象编写了程序,现在我用事件对象进行了尝试。 想法是使用N事件自动重置和单事件手动重置 N个事件被N个“读取”线程用来向Wai

我正在学习C Windows编程,特别是线程、并发和同步。

为了进行实验,我正在编写一个接受N个参数的C程序。
每个参数表示文件系统目录树的路径,程序必须比较所有目录的内容,以确定所有目录是否具有相同的内容。
main为每个参数运行一个“读取”线程,而单个“比较”线程则比较找到的所有条目的名称。对于找到的每个文件/目录,“读取”线程通过激活“比较”线程进行同步

我用
信号量
对象编写了程序,现在我用
事件
对象进行了尝试。
想法是使用
N事件自动重置
单事件手动重置

N个事件被N个“读取”线程用来向
WaitForMultipleObjects
中的
无限时间的“比较”线程发送信号。当所有信号可用时,它开始比较条目,然后对手动重置对象执行
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);

     }

}
DWORD WINAPI CompareThread(LPVOID arg){
while(条目相等){
WaitForMultipleObjects(N,glphReadingEvent,TRUE,1000);
对于(r=0;r
问题:

有时,一个读数线程能够在不考虑同步器与其他线程的情况下工作。如果我在Wait和比较线程Set之间放置一个
printf()
Sleep(1)
,程序工作得很好

我的意见:

我认为手动重置事件对于这种(屏障)同步是不安全的。
ResetEvent()
中的读取线程可能太快,如果计划程序减慢了其他线程的速度,则在执行重置的线程能够继续工作时,其中一些线程可能会处于阻塞状态。
但是,如果是这种情况,比较线程应在
WaitingForMultipleObjects
上阻塞自身,从而导致死锁。。。实际上,没有死锁,但是一个线程相对于其他线程能够循环更多的时间。

我想理解的是为什么简单的睡眠可以解决这个问题。是调度问题还是同步的错误实现


谢谢。

我忘了提到glphReadingEvent是自动重置的。在windows开发中心,我读到“一个事件对象,其状态保持有信号状态,直到释放一个等待线程,此时系统自动将状态设置为无信号状态。”