1

我刚刚在 C 中实现了一个读写器锁。我想限制读者的数量,所以我使用 'num' 来计算它。我不确定这个实现是否有一些潜在的数据竞争或死锁条件。那么你能帮我弄清楚它们吗?

另一个问题是我可以以某种方式删除 struct _rwlock 中的“spin_lock”吗?谢谢!

#define MAX_READER 16; 
typedef _rwlock *rwlock;
struct _rwlock{
    spin_lock   lk;
    unint32_t   num;
};
void wr_lock(rwlock lock){
    while (1){
        if (lock->num > 0) continue;
        lock(lock->lk);
        lock->num += MAX_READER;
        return;
    }
}
void wr_unlock(rwlock lock){
    lock->num -= MAX_READER;
    unlock(lock->lk);
}
void rd_lock(rwlock lock){
    while (1){
        if (lock->num >= MAX_READER) continue;
        atom_inc(num);
        return;
    }
}
void rd_unlock(rwlock lock){
    atom_dec(num);
}
4

2 回答 2

2

wr_lock(和类似的rd_lock):

while (1){
    if (lock->num > 0) continue;

这是错误的。如果您不以某种方式同步,则不能保证看到来自其他线程的更改。如果这是唯一的问题,您也许可以获取锁,然后检查计数。

rd_lock

atom_inc(num);

这不适用于非原子函数+=-=编写器函数,因为它可能会中断它们。中的减量也是如此rd_unlock

rd_lock可以在线程持有锁作为写入器时返回——这不是读写锁的通常语义,这意味着无论您的 rw-lock 应该保护什么,它都不会保护它。

如果您使用的是 pthreads,那么它已经有一个 rwlock。在 Windows 上考虑 SRWlocks(我自己从未使用过它们)。对于可移植代码,使用条件变量(或者可能两个——一个用于读取器,一个用于写入器)构建您的 rwlock。也就是说,只要 C 中的多线程代码可以移植。C11 有一个条件变量,如果有一个 C11 之前的线程实现没有,我不想使用它;-)

于 2012-10-07T19:35:30.447 回答
2

简短的回答:是的,这里有严重的问题。我不知道您使用的是什么同步库,但是您没有保护对共享数据的访问,并且您将在 rd_lock() 和 wr_lock() 中的循环上浪费大量 CPU 周期。几乎在所有情况下都应避免自旋锁(但也有例外)。

于 2012-10-07T19:11:42.720 回答