我正在尝试使用共享变量和互斥锁来同步三个pthread,以便它们创建输出:123123123 ...但是,我能想到的就是使用while循环,如下面的代码所示。
是否可以使代码更优雅,而无需使线程休眠并使用while循环?
#include
#include
#include
#include
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;
}
您可能正在寻找有条件的等待。
当多个线程尝试同时获取互斥对象时,它们中的任何一个都可以获取它。因此,如果"错误"线程获取了互斥锁,则它必须以某种方式屈服,以便正确的线程获取互斥锁。在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
将多个变量传递给线程函数的方式与传递字符非常相似。您可以使用结构来代替char。例如:
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()唤醒所有已经等待条件变量的线程。
在正常情况下,我们只唤醒一个线程,以尝试避免所谓的雷电群问题。仅使用三个线程就不是一个真正的问题,但是我认为在这里介绍这个概念可能是一个好主意。仅当发现当前线程不合适时,我们才唤醒所有等待条件变量的线程。
如果只用信号通知条件变量,则可能有两个错误的线程交替出现;这就是为什么我们确实需要该广播。