问题在于:
我想写一个创建10个线程的短程序,每个程序打印一个通过指针传递给线程函数的“id”.
该计划的完整代码如下:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct params {
pthread_mutex_t mutex;
int id;
};
typedef struct params params_t;
void* hello(void* arg){
int id;
pthread_mutex_lock(&(*(params_t*)(arg)).mutex);
id = (*(params_t*)(arg)).id;
pthread_mutex_unlock(&(*(params_t*)(arg)).mutex);
printf("Hello from %d\n",id);
}
int main() {
pthread_t threads[10];
params_t params;
pthread_mutex_init (¶ms.mutex,NULL);
int i;
for(i = 0; i < 10; i++) {
params.id = i;
if(pthread_create(&threads[i],NULL,hello,¶ms));
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i],NULL);
}
return 0;
}
假定的输出(按此顺序不必要):
Hello from 0 .... Hello from 9
实际结果是:
Hello from 2 Hello from 3 Hello from 3 Hello from 4 Hello from 5 Hello from 6 Hello from 8 Hello from 9 Hello from 9 Hello from 9
我试图将互斥锁放在hello()函数的不同位置,但它没有帮助.
我该如何实现线程同步?
编辑:假设结果不是必要的0 … 9它可以是这些数字的任意组合,但每一个应该只出现一次.
解决方法
有两个问题:
答:你正在使用锁,但主要不知道这个锁.
B.在这种情况下锁定是不够的.你想要的是线程通过相互发信号来协作(因为你希望main不会增加变量,直到一个线程说它完成打印它).您可以使用pthread_cond_t来实现此目的(Look here以了解有关此内容的更多信息).这归结为以下代码(基本上,我在代码中添加了适当的pthread_cond_t用法,以及一堆解释正在发生的事情的注释):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct params {
pthread_mutex_t mutex;
pthread_cond_t done;
int id;
};
typedef struct params params_t;
void* hello(void* arg){
int id;
/* Lock. */
pthread_mutex_lock(&(*(params_t*)(arg)).mutex);
/* Work. */
id = (*(params_t*)(arg)).id;
printf("Hello from %d\n",id);
/* Unlock and signal completion. */
pthread_mutex_unlock(&(*(params_t*)(arg)).mutex);
pthread_cond_signal (&(*(params_t*)(arg)).done);
/* After signalling `main`,the thread Could actually
go on to do more work in parallel. */
}
int main() {
pthread_t threads[10];
params_t params;
pthread_mutex_init (¶ms.mutex,NULL);
pthread_cond_init (¶ms.done,NULL);
/* Obtain a lock on the parameter. */
pthread_mutex_lock (¶ms.mutex);
int i;
for(i = 0; i < 10; i++) {
/* Change the parameter (I own it). */
params.id = i;
/* Spawn a thread. */
pthread_create(&threads[i],¶ms);
/* Give up the lock,wait till thread is 'done',then reacquire the lock. */
pthread_cond_wait (¶ms.done,¶ms.mutex);
}
for(i = 0; i < 10; i++) {
pthread_join(threads[i],NULL);
}
/* Destroy all synchronization primitives. */
pthread_mutex_destroy (¶ms.mutex);
pthread_cond_destroy (¶ms.done);
return 0;
}
我看到你正在尝试的例子是一个可能了解POSIX线程库的玩具程序.在现实世界中,我们都知道,即使不使用线程,也可以更快地完成.但你已经知道了.