在 C 中使用共享变量和互斥锁进行线程同步
Posted
技术标签:
【中文标题】在 C 中使用共享变量和互斥锁进行线程同步【英文标题】:Thread synchronizing using shared variables and mutex in C 【发布时间】:2018-11-19 11:27:31 【问题描述】:我正在尝试使用共享变量和互斥锁同步三个 pthread,以便它们创建输出:123123123... 但是,我能想到的只是使用 while 循环,如下面的代码所示。 是否可以让代码更优雅,而不让线程休眠和使用while循环?
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
static pthread_mutex_t cs_mutex;
char p;
int q;
void* print(void *pParam)
char c = *(char*)pParam;
int i;
for (i = 0; i < 100; i++)
while(p!=c) sleep(0.2);
pthread_mutex_lock(&cs_mutex);
printf("%c", c);
fflush(stdout);
q=(q+1)%4;
if(q==0)q=1;
p=q+48;
pthread_mutex_unlock(&cs_mutex);
return 0;
int main(void)
pthread_t hPrint1;
pthread_t hPrint2;
pthread_t hPrint3;
pthread_mutex_init(&cs_mutex, NULL);
char c1 = '1';
char c2 = '2';
char c3 = '3';
p=c1;
q=1;
pthread_create(&hPrint1, NULL, print, (void*)&c1);
pthread_create(&hPrint2, NULL, print, (void*)&c2);
pthread_create(&hPrint3, NULL, print, (void*)&c3);
getchar();
pthread_mutex_destroy(&cs_mutex);
return 0;
【问题讨论】:
您可能正在寻找条件等待。 【参考方案1】:当多个线程同时尝试获取互斥体时,其中任何一个都可以获取它。因此,如果“错误”线程获取了互斥锁,它必须以某种方式让步,以便正确的线程获取互斥锁。在 OP 的代码中,sleep(0.2)
尝试执行此操作。 (这是一个忙碌的等待,并不能按预期工作,因为 unistd.h sleep()
将整数秒数作为参数。)
更好的选择是使用互斥体、条件变量和序列索引作为共享变量。在伪代码中,每个线程都会这样做:
Function Thread(mynumber, mychar):
Lock mutex
Loop:
Wait on condition variable
If index >= limit:
Signal on condition variable
Unlock mutex
Return
Else
If (index % mynumber == 0):
Output mychar
Signal on condition variable
Else:
Broadcast on condition variable
End If
End Loop
End Function
将多个变量传递给线程函数的方式与传递字符的方式非常相似。而不是一个字符,你只使用一个结构。例如:
struct work
int mynumber; /* Thread number: 0, 1, 2 */
int mychar; /* Character to output: '1', '2', '3' */
;
您可以将struct work w[3];
声明为全局变量或在您的main()
中,并使用例如初始化它
struct work w[3];
w[0].mynumber = 0; w[0].mychar = '1';
w[1].mynumber = 1; w[1].mychar = '2';
w[2].mynumber = 2; w[2].mychar = '3';
并将他们的地址称为&(w[0])
(或等同于&w[0]
)。
在线程函数中,可以使用例如
void *worker(void *payload)
struct work *const w = payload;
/* w->mynumber is the number (0, 1, 2) of this thread,
w->mychar is the char ('1', '2', '3') to output */
注意pthread_cond_signal()
唤醒一个已经在条件变量上等待的线程,pthread_cond_broadcast()
唤醒所有已经在条件变量上等待的线程。
在正常情况下,我们只唤醒一个线程,尽量避免所谓的thundering herd problem。仅仅三个线程并不是一个真正的问题,但我认为在这里引入这个概念可能是一个好主意。只有当我们发现当前线程不是正确的线程时,我们才会唤醒所有等待条件变量的线程。
如果我们只在条件变量上发出信号,那么两个错误的线程可能会交替出现;这就是我们真正需要广播的原因。
【讨论】:
以上是关于在 C 中使用共享变量和互斥锁进行线程同步的主要内容,如果未能解决你的问题,请参考以下文章