我正在尝试执行多编写器程序,其中每个编写器线程逐个获取队列的锁定,然后多个读取器读取它。以下代码适用于第一个编写器,但它没有为第二个编写器自己的病房提供所需的输出实际上编写器线程函数在第一次迭代后没有被调用。请帮助..
for(i = 0; i < wno; i++)
{
fflush(stdin);
ret = pthread_create(&writter[i], NULL, write_to_queue, NULL);
if( ret != 0)
{
printf("Could not create Thread \n");
break;
}
else
{
sleep(10);
printf("Value of ret %d\n", ret);
for(j = 0; j < rno; j++)
{
pthread_create(&reader[t], NULL, read_from_queue, NULL);
//sleep(2);
t++;
}
sleep(1);
}
void *write_to_queue()
{
int ch;
pthread_mutex_lock(&lock);
while(ch != 0)
{
fflush(stdin);
printf("Choose one of the following to proceed\nPress 1 to EnQueue\nPress 2 to DeQueue\nPress 0 to Exit\n");
scanf("%d", &ch);
getchar();
switch(ch)
{
case 0 : ch = 0; break;
case 1 : EnQueue(); break;
case 2 : DeQueue(); break;
default : printf("Please Enter a valid Choice\n"); break;
}
}
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
读者线程工作正常。
答案 0 :(得分:2)
在进入循环之前获取lock
,并且仅在离开循环后才释放。
如果您希望线程在每次迭代时进行竞争,请将获取和释放调用移到循环内。请注意,您的代码在阅读ch
未初始化时具有未定义的行为。下面的代码修复了这个问题。
int ch = -1; // Initialize!
while (ch != 0) {
pthread_mutex_lock(&lock);
printf("%s",
"Choose one of the following to proceed\n"
"Press 1 to EnQueue\n"
"Press 2 to DeQueue\n"
"Press 0 to Exit\n");
scanf("%d", &ch);
getchar();
switch(ch) {
case 0 : ch = 0; break;
case 1 : EnQueue(); break;
case 2 : DeQueue(); break;
default : printf("Please Enter a valid Choice\n"); break;
}
pthread_mutex_unlock(&lock);
}
作为多线程编程设计的一个问题,你应该避免“胖锁综合症”。 胖锁是一种在线程代码的一个非常大的段上序列化执行的方法,它实际上删除了程序中的任何并行执行。
为了实现并行性,应该使用更精细的方法来保护关键部分。这意味着锁获取和释放仅与需要它的代码部分隔离。这通常意味着对特定共享数据结构的操作,在您的情况下,它将是EnQueue
和DeQueue
操作。
您的特定程序似乎是I / O很重。不幸的是,如果您想要一致的I / O行为,则必须将访问stdin
和stdout
视为关键部分。但是,您可以考虑创建一个单独的I / O线程,该线程可以与stdin
和stdout
进行交互而无需锁定。可以将选择放在工作队列上,工作线程可以在工作队列上等待执行工作。当每个线程处理所请求的工作时,它可以根据需要执行粒度锁定以完成工作。