2017-09-25 43 views
0

下一个代码通常打印BA,但有时它可以打印BBAA,BAAB,... ...这怎么可能得到两个A或B吧?但是,这段代码从不打印三个A或B.这两个函数(生产和消费)都运行很多线程。提前谢谢了。奇线程行为

int permission; 
void set_permission(int v) { 
    permission = v; 
    printf("%c", v + 'A');fflush(stdin); 
} 
void* produce(void*) { 
    for (;;) { 
     pthread_mutex_lock(&mr1); 
     set_permission(1); 
     while (permission == 1); 
     pthread_mutex_unlock(&mr1); 
    } 
} 
void* consume(void*) { 
    for (;;) { 
     pthread_mutex_lock(&mr2); 
     while (permission == 0); 
     set_permission(0); 
     pthread_mutex_unlock(&mr2); 
    } 
} 
+5

'fflush(标准输入);'导致udnefined行为;不要做 –

+1

我看到2个不相关的互斥体。看起来您可以删除同步过程并获得相同的结果。 –

+0

关于两个不同的互斥体的引用是什么?如果代码试图保护变量'permission',那么所有的互斥量引用应该是同一个互斥量。建议:for(;;){while(!permission);的pthread_mutex_lock(&mr1); set_permission(1);调用pthread_mutex_unlock(&mr1);}'消费者线程看起来非常相似,并且将使用相同的互斥 – user3629249

回答

4

您的线程不同步,因为它们不使用相同的互斥锁。

其他线程可以通过只偶然奶源设置permission为1或0,但不能管理产生输出呢。在这种情况下,看起来好像第一个线程运行了两轮。

当内核之间的内存同步并且两个线程都写入时,相应线程的写入也可以完全获得丢失。互斥体也可以防止这种情况发生,因为它建立了一个严格的内存访问顺序,简单来说,它保证了在一个互斥体的保护下发生的所有事情对同一个互斥体的下一个用户完全可见。

3次或更多次打印相同的字符将是非常不可能的,因为有至多一个写之间发生的,所以至多一个写丢失,或一个无序的输出。虽然这并不能保证。

如果您的系统上没有隐含内存同步工作可言,你的代码也只是直出僵局,下一个互斥体完成写入从未传播到另一个的用户。 (实际上并没有发生,因为仍然有一些同步由IO操作介绍。)

+0

我在作业前放置了printf,这消除了所有双字符!太感谢了! – vollitwr

+1

@vollitwr只要你不使用相同的互斥量,这仍然只是消除了乱序输出。你的代码仍然容易丢失写入,除非'permission'是[atomic](http://de.cppreference.com/w/cpp/atomic/atomic),或者你正在使用相同的互斥体。这个错误很难激发,但它仍然会发生。 – Ext3h