问题在于:
我想写一个创建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线程库的玩具程序.在现实世界中,我们都知道,即使不使用线程,也可以更快地完成.但你已经知道了.