私は現在、Reader-Writer問題の正しい実装に取り組んでいます(ここを参照)。
このソリューションは、セマフォとミューテックスを使用してリーダースレッドとライタースレッドの公平な処理を保証するQtドックで見つかりました。基本的なコードは次のとおりです。
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_);
}
これは非常にエレガントな解決策のようです。このSOの回答pthread_rwlock_*
で詳しく説明されている動作よりも簡単で効率的です。
以下のこのコードは、リーダースレッドを優先するためのQtソリューションの正しい調整であるかどうか疑問に思いました。
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_);
}