【问题标题】:Does WaitOnAddress return when values match or when values differ?当值匹配或值不同时,WaitOnAddress 是否返回?
【发布时间】:2021-01-04 03:29:06
【问题描述】:

我正在尝试使用WaitOnAddress()函数来实现读写同步。

According to MSDNWaitOnAddress() 具有以下声明:

BOOL WaitOnAddress(
  volatile VOID *Address,
  PVOID         CompareAddress,
  SIZE_T        AddressSize,
  DWORD         dwMilliseconds
);

以及如下参数定义:

比较地址

指向先前观察到的值在Address 的位置的指针。当Address 的值与CompareAddress 的值不同时,该函数返回。

根据定义,我应该存储并传递被监视地址的当前值,所以当监视值发生变化时,WaitOnAddress() 会返回。但是这个功能并没有像我预期的那样工作,所以我在 Visual Studio 中为WaitOnAddress() 编写了以下测试代码(还包括链接器库Synchronization.lib):

#include <stdio.h> 
#include <stdlib.h>  // atoi 
#include <string.h> 

// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>
#include <synchapi.h>

void* threads(void* num) {
    int* number = (int*)num;
    for (int i = 0; i < 10; i++) {
        printf("number = %d\n", *number);
    }
    int catch = *number; // will be passed as CompareAddress
    WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
    for (int i = 0; i < 10; i++) {
        printf("number2 = %d, %d\n", catch, *(int*)num);
    }
    return NULL;
}

int main() {
    int int_list[10];
    for (int i = 0; i < 10; i++) {
        int_list[i] = i;
        _beginthread(threads, 0, (void*)&int_list[i]);
    }
    printf("hello\n");
    Sleep(1000);
    for (int i = 0; i < 10; i++) {
        int_list[i] = 10 - i;
    }
    printf("changed\n");
    Sleep(1000);
    return 0;
}

在上面的代码中,WaitOnAddress() 永远不会返回,即使它监视的值发生了变化。但是,如果我改变了

int catch = *number;

到:

int catch = 10 - *number;

然后WaitOnAddress() 返回并打印输出的其余部分,就好像它仅在观察值与比较值匹配时才返回。

但是,我想使用所描述的行为,以便在监视变量发生更改时释放我的线程。

【问题讨论】:

  • 在父级更改所有值之前,如何确定线程已达到WaitOnAddress?你能显示输出日志吗?
  • 从您链接到的文档中:“直到同一进程中的另一个线程通过调用 WakeByAddressSingle 或 WakeByAddressAll 或超时,以先到者为准”
  • @kaylum 感谢您提醒我。在另一次修订后,我发现了一个错误的假设,我得出了错误的结论。
  • @RaymondChen 确实,谢谢,我很抱歉。每次阅读该页面时,我怎么会错过那句话?...下次我应该更仔细地阅读手册。顺便说一句,我可以问我应该怎么做我的问题,因为它在stackoverflow中没有意义?我担心删除会是对你们两个发布的消息的不尊重,但我没有找到关闭按钮。

标签: c winapi


【解决方案1】:

根据documentation

参数

地址

等待的地址。如果地址处的值不同于 CompareAddress 的值,函数立即返回。如果 值相同,函数直到另一个线程才返回 在同一过程中,表明 Address 处的值已更改 调用 WakeByAddressSingle 或 WakeByAddressAll 或超时 以先到者为准。

虽然你在第二个循环中修改了原数组的值,但是在线程中调用WaitOnAddresscatchnum总是一样的,所以WaitOnAddress函数不会返回。

你可以尝试修改为:

#include <stdio.h> 
#include <stdlib.h>  // atoi 
#include <string.h> 

// include these two files after including winsock2.h
#include <process.h>
#include <Windows.h>

void* threads(void* num) {
    int* number = (int*)num;
    printf("number = %d\n", *number);
    int catch = *number; // will be passed as CompareAddress
    WaitOnAddress((int*)num, &catch, sizeof(int), INFINITE);
    printf("number2 = %d, %d\n", catch, *(int*)num);
    return NULL;
}

int main() {
    int int_list[10];
    for (int i = 0; i < 10; i++) {
        int_list[i] = i;
        _beginthread(threads, 0, (void*)&int_list[i]);
    }
    printf("hello\n");
    Sleep(1000);
    printf("changed\n");
    for (int i = 0; i < 10; i++) {
        int_list[i] = 10 - i;
        WakeByAddressSingle(&int_list[i]);
    }
    Sleep(1000);
    return 0;
}

它对我有用:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多