在 C 中使用带有分离线程的互斥量

Using mutexes with detached threads in C

#define SIZE 10

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

show(void *arg)
{
    pthread_mutex_lock(&mutex);
    int i = *(int *)arg;
    printf("%d\n", i);
    pthread_mutex_unlock(&mutex);
}

main()
{
    pthread_t threads[SIZE];
    pthread_attr_t attr;
    
    pthread_mutex_init(&mutex, NULL);
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        
    int i;
    for (i = 0; i < SIZE; i++)
        assert(!pthread_create(&threads[i], &attr, show, &i));
}

我在将值“i”传递给我的分离线程时遇到了问题。它应该传递从 0 到 9 的数字,但它不是那样工作的。我应该怎么做才能让它发挥作用?

不能保证您启动的线程会立即 运行 并从您传递给它的指针中获取 i 的正确值。在第一个线程开始运行时,main 可能已经(例如)五次 次循环迭代,每次都更新 i ,这意味着第一个线程将拾取一些大于应有值的值。

立即想到两种可能的解决方案:

  1. 确保 main 暂停,直到线程启动并获取 i 的正确值。这很麻烦,因为它涉及从线程到 main(例如条件变量)的一些反向通信。
  2. 在指针中传递 i 而不是指向 i 的指针。这确保了该值的本地副本被提供给线程,而不是依赖于指向可能变化的值的指针。

第一个选项是这样的,伪代码,因为我懒得去查找 POSIX 条件变量调用:

main:
    for i in 0..9:
        start thread passing address of i
        await condvar

thread recieving ptr:
    local i = contents of ptr
    kick condvar
    carry on

第二个选项是我最喜欢的see/do。您可以将线程创建调用更改为类似以下内容:

// Pass i-cast-to-a-pointer, rather than passing pointer-to-i.

assert(!pthread_create(&threads[i], &attr, show, (void*)i));

并在线程中使用:

// Cast pointer back to int rather than dereferencing pointer.

int i = (int)arg;

顺便说一句,线头是否脱落与这里无关。这是线程之间的一般竞争条件。