在循环中创建线程

Thread creation in loop

我正在尝试执行多写入器程序,其中每个写入器线程一个一个地获取队列的锁,然后多个 reader 读取它。以下代码对第一个作者工作正常,但它没有为第二个作者自己的病房提供所需的输出,实际上在第一次迭代后没有调用作者线程函数。请帮助..

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);
}

reader 个线程工作正常。

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);
}   

作为多线程编程设计的问题,你应该避免"fat lock syndrome"。 胖锁 是一种在线程代码的很大一部分上序列化执行的锁,它实际上消除了程序中的任何并行执行。

要实现并行性,应使用更精细的方法来保护关键部分。这意味着锁的获取和释放仅与需要它的代码部分隔离。这通常意味着对特定共享数据结构的操作,在您的情况下,它将是 EnQueueDeQueue 操作。

您的特定程序似乎 I/O 很重。不幸的是,如果您想要一致的 I/O 行为,则必须将访问 stdinstdout 视为关键部分。但是,您可以考虑创建一个单独的 I/O 线程,它可以在不需要锁的情况下与 stdinstdout 交互。选择可以放在工作队列上,工作线程可以在工作队列上等待执行工作。当每个线程处理请求的工作时,它可以根据需要执行粒度锁定以完成工作。