在读写线程中使用旗语。

问题描述 投票:0回答:1

我有一个问题,我有多个线程(读线程),其中共享数据要被读取,到目前为止没有问题,这个共享数据要在另一个单一线程(写线程)中更新。

在这个写的过程中,为了防止数据损坏,不应该进行读。

我最初的想法是在做完一些读取后,使用semaphore(Posix semaphore,)。

使用sem_wait()和sem_post()在读线程里面对semaphore进行阻断、递减和递增,效果还不错。只要semaphore不是0,sem_wait()就不会阻塞,允许线程读取数据。

我的问题从这里开始。现在我想让写线程的条件与sem_wait()的实际操作相反。我希望只要semaphore大于0,写线程就会被阻塞,因为这意味着有一个读线程在进行。

有没有什么方法可以让它在semaphore大于0的时候被阻塞,或者有什么不同的方法可以解决这个问题?

谢谢!请问有什么办法可以解决这个问题?

c multithreading semaphore
1个回答
1
投票

一种选择是使用POSIX 读写锁,在这种情况下,除非有一个写手,否则多个读者都可以获得锁。

另一种选择是低级别的 seqlock 但它的实施和正确使用可能会比较棘手,因为它需要很好的掌握 记忆模型 数据竞赛和内存顺序。


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需要记住有多少个写者在等待[你不想在任何一个条件下盲目地发布]。

© www.soinside.com 2019 - 2024. All rights reserved.