在 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
,这意味着第一个线程将拾取一些大于应有值的值。
立即想到两种可能的解决方案:
- 确保
main
暂停,直到线程启动并获取 i
的正确值。这很麻烦,因为它涉及从线程到 main
(例如条件变量)的一些反向通信。
- 在指针中传递
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;
顺便说一句,线头是否脱落与这里无关。这是线程之间的一般竞争条件。
#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
,这意味着第一个线程将拾取一些大于应有值的值。
立即想到两种可能的解决方案:
- 确保
main
暂停,直到线程启动并获取i
的正确值。这很麻烦,因为它涉及从线程到main
(例如条件变量)的一些反向通信。 - 在指针中传递
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;
顺便说一句,线头是否脱落与这里无关。这是线程之间的一般竞争条件。