C-使用指针和线程时避免种族条件



我是为了自己的娱乐修补此代码:

#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>
void print_message(void *param)
{
    int thread_counter = *((int*)param);
    printf("Thread #%irn", thread_counter);
    _endthreadex(0);
}
int main()
{
    unsigned thread_ID;
    HANDLE thread_handle;
    int thread_count = 10;
    HANDLE thread_handles[thread_count];
    for(int i = 0; i < thread_count; i++) 
    {
        thread_handles[i] = (HANDLE)_beginthreadex(NULL, 0, &print_message, &i, 0, &thread_ID);
        thread_handle = thread_handles[i];
    }
    WaitForMultipleObjects(thread_count, thread_handles, TRUE, INFINITE);
    return EXIT_SUCCESS;
}

a

Output
Thread #8
Thread #10
Thread #10
Thread #10
Thread #10
Thread #10
Thread #10
Thread #10
Thread #10
Thread #10

我认为问题是我正在传达对变量i的引用,而在线程使用/操纵此引用时,for循环中的变量i正在逐渐增加。

我如何避免竞赛条件,并将变量i的值传递给线程函数?

我也想将字符串/字符阵列传递到线程功能,但我似乎不明白如何做。

我正在使用Windows 10

上的小C编译器(TCC(

不要将指针传递给 i,传递 value 存储在 i本身中:

void print_message(void *param)
{
    int thread_counter = (intptr_t)param;
    printf("Thread #%irn", thread_counter);
    _endthreadex(0);
}
// ... rest of code ...
    // We cast the value in i to a pointer width integer value, intptr_t
    // to explicitly match the size of the void* we're smuggling it in
    thread_handles[i] = (HANDLE)_beginthreadex(NULL, 0, &print_message, (void*)(intptr_t)i, 0, &thread_ID);
// ... rest of code ...

如果您所传递的只是一个小于指针宽度值,则可以将其值作为"指针"值本身走私。在这种情况下,您只需将其抬高到intptr_t(与指针的宽度匹配的整数类型(,然后在提取上降低。

因为实际值是传递的,而不是指向它的指针,因此在调用_beginthreadex之前制作副本,然后修改i之后不会更改任何内容。

如果要传递的数据更大,那么您要么施加某种障碍(以确保在主线程再次触摸i之前读取值(或使用动态内存使用(分配空间,在值,将指针传递给分配内存到线程,线程在释放空间之前提取值(。第三个选项是值的数组,每个线程一个(因此第一个线程接收&arr[i],其中i0,下一个&arr[i]用于i == 1,等等(。

您可以传递值,而不是与此相似的指针。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
void print(void *foo){
    intptr_t bar = (intptr_t)foo; 
    printf("%" PRIdPTR "n",bar); 
}
int main(void)
{
    intptr_t i=1;
    print((void*)i);
    return 0;
}

您只需要小心,该功能确实将其视为值。在功能本身中,您必须确保施放的变量可以采用指针的大小。(这是通过使用intptr_t完成的(

为了避免赛车通用,您可以使用静音者,但这在这里并不有用。

您可以以某种方式发出信号,说该值已在线程中读取并让循环等待直到那时,但这会使线程变得毫无用处。

相关内容

  • 没有找到相关文章

最新更新