我刚刚在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);
}
答案 0 :(得分:2)
简短回答:是的,这里有严重的问题。我不知道您正在使用什么同步库,但是您不保护对共享数据的访问,并且您将在rd_lock()和wr_lock()中浪费大量的CPU周期。几乎在所有情况下都应该避免旋转锁(但也有例外)。
答案 1 :(得分:2)
在wr_lock
(以及rd_lock
中的类似内容):
while (1){
if (lock->num > 0) continue;
这是错误的。如果你不以某种方式同步,你不能保证看到来自其他线程的变化。如果这是唯一的问题,你可能会获得锁,然后检查计数。
在rd_lock
:
atom_inc(num);
这对于编写器函数中的非原子+=
和-=
并不好用,因为它可以中断它们。与rd_unlock
中的减量相同。
rd_lock
可以在线程将锁保存为编写器时返回 - 这不是读写器锁的常用语义,这意味着无论你的rw-lock应该保护什么,它不会保护它。
如果您使用的是pthread,那么它已经有了一个rwlock。在Windows上考虑SRWlocks(从未使用过'我自己)。对于可移植代码,使用条件变量(或者两个 - 一个用于读者,一个用于编写者)构建rwlock。也就是说,只要C 中的多线程代码可以可移植。 C11有一个条件变量,如果有一个前C11线程实现那里没有,我不想要使用它; - )