【问题标题】:Use of semaphores in read/write threads在读/写线程中使用信号量
【发布时间】:2020-04-26 11:24:00
【问题描述】:

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

在此写入期间,不应进行读取以防止损坏数据。

我最初的想法是在阅读后使用信号量(Posix 信号量,)。

使用 sem_wait() 和 sem_post() 可以很好地阻止、减少和增加读取线程内的信号量。只要信号量不为 0,sem_wait() 就不会阻塞并允许线程读取数据。

我的问题从这里开始。 现在我想让写线程的条件与 sem_wait() 的实际作用相反。只要信号量大于零,我希望写入线程被阻塞,因为这意味着有一个读取线程正在进行中。

当信号量大于 0 时,有什么方法可以阻止它,或者有什么不同的方法可以解决这个问题?

谢谢!

【问题讨论】:

  • 信号量是一个糟糕的选择。 POSIX 提供读/写锁。但实际上最好只使用互斥锁,因为它的锁定/解锁开销最小。

标签: c multithreading semaphore


【解决方案1】:

一种选择是使用 POSIX read-write lock,其中多个读取器可以获取锁,除非有写入器。

另一个选项是较低级别的seqlock,但正确实施和使用可能会比较棘手,因为它需要很好地掌握memory model 数据竞争和内存顺序。

【讨论】:

    【解决方案2】:

    如果您必须使用信号量,并且处于 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);
    }
    

    在功能上,lock 是结构体的互斥体,wwrite、wread 分别作为写者和读者的条件变量。 nreaders 需要记住有多少并发读者(因为你不能等待 +tive 信号量)和 nwriters 需要多少作者在等待[你不想在任何一种情况下盲目发帖]。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 2021-08-05
      • 1970-01-01
      • 2012-12-22
      相关资源
      最近更新 更多