我正在按顺序获取一些资源。哪个版本更好?有人告诉我,#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)
编辑: 事实证明,释放资源的顺序会产生差异,而不是上面的构造。如果你按顺序释放它们就会发生饥饿,如果相反则可能不会发生。
答案 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
函数中锁定和解锁,然后只在等待之前锁定 - 在它之后立即解锁。