我有一个问题,我有多个线程(读线程),其中共享数据要被读取,到目前为止没有问题,这个共享数据要在另一个单一线程(写线程)中更新。
在这个写的过程中,为了防止数据损坏,不应该进行读。
我最初的想法是在做完一些读取后,使用semaphore(Posix semaphore,)。
使用sem_wait()和sem_post()在读线程里面对semaphore进行阻断、递减和递增,效果还不错。只要semaphore不是0,sem_wait()就不会阻塞,允许线程读取数据。
我的问题从这里开始。现在我想让写线程的条件与sem_wait()的实际操作相反。我希望只要semaphore大于0,写线程就会被阻塞,因为这意味着有一个读线程在进行。
有没有什么方法可以让它在semaphore大于0的时候被阻塞,或者有什么不同的方法可以解决这个问题?
谢谢!请问有什么办法可以解决这个问题?
如果你一定要使用semaphores,而且是在unix-y的环境中,我想你只能用这样的方法。
typedef struct rwl RWL;
struct rwl {
sem_t lock;
sem_t wread;
sem_t wwrite;
int nreaders;
int nwriters;
};
void RWL_REnter(RWL *l) {
while (1) {
sem_wait(&l->lock);
l->nreaders++;
if (l->nwriters) {
sem_post(&l->lock);
sem_wait(&l->wread);
} else {
sem_post(&l->lock);
break;
}
}
}
void RWL_WEnter(RWL *l) {
while (1) {
sem_wait(&l->lock);
l->nwriters++;
if (l->nreaders || l->nwriters > 1) {
sem_post(&l->lock);
sem_wait(&l->wwrite);
} else {
sem_post(&l->lock);
break;
}
}
}
void RWL_WExit(RWL *l) {
sem_wait(&l->lock);
if (--(l->nwriters)) {
sem_post(&l->wwrite);
} else while (l->nreaders--) {
sem_post(&l->wread);
}
sem_post(&l->lock);
}
void RWL_RExit(RWL *l) {
sem_wait(&l->lock);
if (--(l->nreaders)) {
sem_post(&l->wread);
} else if (l->nwriters--) {
sem_post(&l->wwrite);
}
sem_post(&l->lock);
}
功能上,锁是结构的mutex, wwrite,wread分别作为写者和读者的条件变量。 nreaders需要记住有多少个并发的读者(因为你不能在+tive旗语上等待),nwriters需要记住有多少个写者在等待[你不想在任何一个条件下盲目地发布]。