资源获取和pthreads

时间:2011-01-23 23:18:14

标签: c resources pthreads

我正在按顺序获取一些资源。哪个版本更好?有人告诉我,#2导致需要更高编号资源的线程饥饿。这是真的?如果是这样,如何以及为什么?

a[] sorted array 

1

for(int i = 1; i < N; ++i) {
  lock(mutex)
  while(!resource_available[a[i]]) {
    pthread_cond_wait(&cond_w[a[i]], &mutex);
  }
  resource_available[a[i]] = 0;
  unlock(mutex)
}

2

lock(mutex)
for(int i = 1; i < N; ++i) {
  while(!resource_available[a[i]]) {
    pthread_cond_wait(&cond_w[a[i]], &mutex);
  }
  resource_available[a[i]] = 0;
}
unlock(mutex)

编辑: 事实证明,释放资源的顺序会产生差异,而不是上面的构造。如果你按顺序释放它们就会发生饥饿,如果相反则可能不会发生。

3 个答案:

答案 0 :(得分:3)

两者几乎都是等价的,因为在示例1中,线程几乎总是重新获取互斥锁而不会在解锁之后立即休眠,因为在它们之间只评估了两个表达式。

答案 1 :(得分:2)

当资源始终可用且pthread_cond_wait不需要运行时,它会导致更多的饥饿。在这种情况下,您将拥有整个循环的互斥锁。因此,如果N非常大,那么通过锁定整个循环外部,可能会使需要互斥锁的其他线程处于饥饿状态。

通常最好锁定最小区域nescesarry以避免其他线程和死锁的饥饿。

当有人来维持这个循环时也要考虑。它很容易在for循环的主体中添加一些额外的if语句/函数调用并创建更多的饥饿。维护者可能很容易错过代码中的锁定。你最好通过创建一个负责获取资源i的功能来阻止这种情况。这个函数负责所有锁定,消除了调用代码扩展临界区大小的任何可能性。

 // blocks till resource resourceNum is obtained
 void acquire_resource(int resourceNum)
 {
     lock(mutex)
     while(!resource_available[a[i]]) {
       pthread_cond_wait(&cond_w[a[i]], &mutex);
     }
     unlock(mutex)
 }

 for(int i = 1; i < N; ++i) {
     acquire_resource(i);
 }

答案 2 :(得分:0)

我会在resource_available函数中锁定和解锁,然后只在等待之前锁定 - 在它之后立即解锁。