Pthreads - 使用互斥锁和繁忙的等待编写可重用的屏障

时间:2017-03-02 14:50:15

标签: pthreads

以下是我正在努力解决的功课问题,因为我病了,错过了讲座。

循环体中的代码是尝试使用互斥锁和繁忙等待来实现可重用障碍。但是,此代码可能会死锁。修复它,使屏障在for循环的每次迭代中正常工作。

Line  1:    // count1 and count2 are volatile and initialized to zero
Line  2:    for (…) { // many iterations
Line  3:        pthread_mutex_lock(&barrier_mutex);
Line  4:        count1++;
Line  5:        count2 = 0;
Line  6:        pthread_mutex_unlock(&barrier_mutex);
Line  7:        while (count1 < threads);
Line  8:    
Line  9:        // do some computation here
Line 10:    
Line 11:        pthread_mutex_lock(&barrier_mutex);
Line 12:        count2++;
Line 13:        count1 = 0;
Line 14:        pthread_mutex_unlock(&barrier_mutex);
Line 15:        while (count2 < threads);
Line 16:    }

我想自己学习这些材料,因为我似乎找到了使用我们在课堂上没有学到的材料的解决方案(例如,不使用繁忙的等待和互斥体。)

了解问题

我想我理解了这个问题:当最后一个线程在第4行增加时,所有其他线程都从忙线等待第7行释放。如果在最后一个线程通过第7行的忙等待之前到达第12行,这可能会导致问题,对吗?

解决问题

我正在考虑在第8行减少count1,并在第10行检查它已经达到零,但后来我遇到了数据竞争问题。也许是这样的:

for (…) { // many iterations
   pthread_mutex_lock(&barrier_mutex);
   count1++;
   pthread_mutex_unlock(&barrier_mutex);
   while (count1 < threads);

   // do some computation here

   pthread_mutex_lock(&barrier_mutex);
   count2++;
   pthread_mutex_unlock(&barrier_mutex);
   while (count2 < threads);
   pthread_mutex_lock(&barrier_mutex);
   count1--;
   pthread_mutex_unlock(&barrier_mutex);
   while (count1 != 0);
   pthread_mutex_lock(&barrier_mutex);
   count2--;
   pthread_mutex_unlock(&barrier_mutex);
   while (count2 != 0);
}

非常感谢任何帮助或参考资料(我的教科书不包括此内容。)

1 个答案:

答案 0 :(得分:0)

您可以用以下方法替换两个障碍(在循环的开始和结束处):

while (count2 != 0)
    ;

pthread_mutex_lock(&barrier_mutex);
count1++;
if (count1 < threads)
{
    pthread_mutex_unlock(&barrier_mutex);

    while (count2 == 0)
        ;

    pthread_mutex_lock(&barrier_mutex);
}
else
{
    count2 = 1;
}
count1--;
if (count1 == 0)
    count2 = 0;
pthread_mutex_unlock(&barrier_mutex);

count1现在是在屏障处等待的线程数,而count2是一个标志,用于指示屏障当前是否可以等待(&#34;向上&#34;,由{{表示1}})或仍然从最后一次等待中释放线程(&#34;向下&#34;,由0指示)。

想要进入障碍的线程首先旋转直到障碍物上升 - 这避免了你已经识别出的种族,当线程试图进入障碍时它仍然没有完成从最后一次释放线程等待。然后它将自己添加到等待的线程中,如果它不是最后一个线程,则旋转直到屏障关闭。进入屏障的最后一个线程反而使屏障失效。一旦屏障关闭,每个线程都会从服务员列表中移除,并且屏障的最后一个线程会使屏障恢复。

我想到的关键想法是在讲座材料中确定最后一个在屏障上等待的线程,并为其分配额外的内务工作。您还可以看到减少等待计数的想法是在正确的轨道上。

请注意,我无法确定这是你的讲师所追求的答案 - 他们几乎肯定有一些具体的教学点,你应该试着找出你错过的讲座录音是可以的,看看同学是否有可以借阅的讲义,或者直接咨询讲师或导师。