使用信号量的读写器首选项

时间:2011-12-21 09:44:25

标签: c++ multithreading posix readerwriterlock

我目前正在努力正确实现Reader-Writer问题(请参阅here)。

我在Qt底座中找到了this解决方案,通过使用信号量和互斥锁保证了Reader和Writer线程的公平处理。基本代码是:

sem_t semaphore_;
pthread_mutex_t lock_;

void PalindromeDatabase::initializeLocks()
{
    sem_init(&semaphore_, 0, NumberOfReaders_);
    pthread_mutex_init(&lock_, nullptr);
}

void PalindromeDatabase::lockReaders()
{
    sem_wait(&semaphore_);
}

void PalindromeDatabase::unlockReaders()
{
    sem_post(&semaphore_);
}

void PalindromeDatabase::lockWriters()
{
    pthread_mutex_lock(&lock_);
    {
        for (int i = 0; i < NumberOfReaders_; ++i)
            sem_wait(&semaphore_);
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::unlockWriters()
{
    for (int i = 0; i < NumberOfReaders_; ++i)
        sem_post(&semaphore_);
}

这似乎是一个非常优雅的解决方案。它似乎比this SO详细说明的pthread_rwlock_*行为更容易,效率更高。

我想知道下面的代码是否是对Qt解决方案的正确调整,而不是更喜欢Reader线程。

int readersActive_;
sem_t semaphore_;
pthread_mutex_t lock_;
pthread_mutex_t readLock_;
pthread_cond_t wait_;

void PalindromeDatabase::initializeLocks()
{
    sem_init(&semaphore_, 0, numberOfReaders_);
    pthread_mutex_init(&lock_, nullptr);
    pthread_mutex_init(&readLock_, nullptr);
    pthread_cond_init(&wait_, nullptr);
}

void PalindromeDatabase::lockReaders()
{
    pthread_mutex_lock(&lock_);
    {
        pthread_mutex_lock(&readLock_);
        sem_wait(&semaphore_);
        pthread_mutex_unlock(&readLock_);

        ++readersActive_;
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::lockReaders()
{
    pthread_mutex_lock(&lock_);
    {
        pthread_mutex_lock(&readLock_);
        sem_wait(&semaphore_);
        pthread_mutex_unlock(&readLock_);

        ++readersActive_;
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::unlockReaders()
{
    sem_post(&semaphore_);

    pthread_mutex_lock(&lock_);
    {
        --readersActive_;

        if (readersActive_ == 0)
            pthread_cond_signal(&wait_);
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::lockWriters()
{
    pthread_mutex_lock(&lock_);
    {
        if (readersActive_ != 0)
        {
            do
            {
                pthread_cond_wait(&wait_, &lock_);
            } while (readersActive_ != 0);
        }

        pthread_mutex_lock(&readLock_);
        for (int i = 0; i < numberOfReaders_; ++i)
            sem_wait(&semaphore_);
        pthread_mutex_unlock(&readLock_);
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::unlockWriters()
{
    for (int i = 0; i < numberOfReaders_; ++i)
        sem_post(&semaphore_);
}

1 个答案:

答案 0 :(得分:2)

您的代码存在一些问题:

  1. 信号量仅供作者使用,因此没有意义。
  2. 锁定作家时,使用互斥锁,而解锁则不使用互斥锁。
  3. 当#readers变为零时,读者发出信号变化的情况,并且写入器等待条件变量的信号,但不检查条件。
  4. 在锁定编写器时,如果#readers已经为零,则实际上不会锁定。
  5. 考虑到我的说法很简单,锁定仍然很棘手,我想到了它,我希望我用这个伪代码破解它,专注于正确的顺序而不是正确的表示法:

    void lockReader()
    {
      lock(rdmutex);  // make sure Reader and Writer can't interfere during locking
      lock(wrmutex);  // lock mutex so waitfor can unlock
      while (writer_)
        waitfor(wrcv, wrmutex);  // no active writers
    
      ++readers_; // at least 1 reader present
      unlock(wrmutex);
      unlock(rdmutex);
    }
    
    void unlockReader()
    {
      lock(rdmutex);
      bool noReaders = (--readers_ == 0);
      unlock(rdmutex);
      if (noReaders) signal(rdcv); // signal when no more readers
    }
    
    void lockWriter()
    {
      lock(WritersLock);  // only 1 writer allowed
      lock(rdmutex);  // lock mutex so waitfor can unlock and no interference by lockReader
      while (readers_ != 0)
        waitfor(rdcv, rdmutex);  // wait until no more readers
      lock(wrmutex);
      writer_ = true;  // a writer is busy
      unlock(wrmutex);
      unlock(rdmutex);
      // WritersLock is still locked
    }
    
    void unlockWriter()
    {
      lock(wrmutex);
      writer_ = false;
      unlock(wrmutex);
      signal(wrcv);  // no more writer (until WritersLock is unlocked)
    
      unlock(WritersLock);
    }
    

    事实证明,Qt实现更简单,但我的算法不需要提前知道最大数量的读者。