Reader Preferred и Writer Preferred в многопоточности чтения-записи

Мне дали задание написать реализацию Read-Write с использованием потоков POSIX. Я хотел бы знать, правильна ли моя реализация для обоих случаев:

Ужасная попытка стерта

Попытка № 2

Читатель предпочитает:

Переменные:

int readersActive_;

sem_t lock_;
sem_t writeLock_;

Реализация:

void PalindromeDatabase::lockReaders()
{
    sem_wait(&lock_);
    {
        ++readersActive_;

        if (readersActive_ == 1)
            sem_wait(&writeLock_);
    }
    sem_post(&lock_);
}

void PalindromeDatabase::unlockReaders()
{
    sem_wait(&lock_);
    {
        --readersActive_;

        if (readersActive_ == 0)
            sem_post(&writeLock_);
    }
    sem_post(&lock_);
}

void PalindromeDatabase::lockWriters()
{
    sem_wait(&writeLock_);
}

void PalindromeDatabase::unlockWriters()
{
    sem_post(&writeLock_);
}

Писатель Предпочитает:

Переменные:

int readersActive_;
int readersWaiting_;

int writersActive_;
int writersWaiting_;

pthread_mutex_t lock_;
pthread_cond_t read_;
pthread_cond_t write_;

Реализация:

void PalindromeDatabase::lockReaders()
{
    pthread_mutex_lock(&lock_);
    {
        if (writersActive_ || writersWaiting_)
        {
            ++readersWaiting_;

            do
            {
                pthread_cond_wait(&read_, &lock_);
            } while(writersActive_ || writersWaiting_);

            --readersWaiting_;
        }

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

void PalindromeDatabase::unlockReaders()
{
    pthread_mutex_lock(&lock_);
    {
        --readersActive_;

        if (writersWaiting_)
            pthread_cond_signal(&write_);
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::lockWriters()
{
    pthread_mutex_lock(&lock_);
    {
        if (readersActive_ || writersActive_)
        {
            ++writersWaiting_;

            do
            {
                pthread_cond_wait(&write_, &lock_);
            } while(readersActive_ || writersActive_);

            --writersWaiting_;
        }

        writersActive_ = 1;
    }
    pthread_mutex_unlock(&lock_);
}

void PalindromeDatabase::unlockWriters()
{
    pthread_mutex_lock(&lock_);
    {
        writersActive_ = 0;

        if (writersWaiting_)
            pthread_cond_signal(&write_);
        else if (readersWaiting_)
            pthread_cond_broadcast(&read_);
    }
    pthread_mutex_unlock(&lock_);
}

Нити - это весело, они также причиняют боль моему мозгу. Если я не прав, пожалуйста, воздержитесь от прямого ответа, но направьте меня в правильном направлении, так как это домашнее задание, и я, и другие люди, такие как я, наверняка выиграем от решения самостоятельно.

2 ответа

Кстати, я не думаю, что

    // If I'm the last reader, we can let the writers work.
if (--numberOfReadersActive_)
    pthread_cond_signal(&readersActive_);

делает то, что говорит в комментарии. Это также может быть причиной того, что вы зашли в тупик.

Ни один из ваших кодов не является правильным. Вы должны освободить мьютекс, как только вы установили блокировку чтения. Удерживая мьютекс, вы должны организовать блокировку писателя. При снятии блокировки чтения вам необходимо организовать разблокировку устройства записи, если снимается последняя блокировка чтения.

В псевдокоде:

read_lock:
1) Получить мьютекс.
2) Увеличьте счетчик блокировки чтения.
3) Блокировать переменную условия, пока не будет записывающих.
4) Отпустите мьютекс.

read_unlock:
1) Получить мьютекс.
2) Уменьшить счетчик чтения.
3) Если счетчик блокировок чтения равен нулю, просыпаются писатели.
4) Отпустите мьютекс.

WRITE_LOCK:
1) Получить мьютекс.
2) Если вы используете приоритет писателя, постарайтесь, чтобы не было новых читателей.
3) Блокируйте переменную условия, пока нет активных читателей. (Вам нужно заблокировать освобождение мьютекса, иначе читатели не смогут завершить операции разблокировки!)

write_unlock:
1) Разбудить ожидающих читателей / писателей (что зависит от приоритета, который вы реализуете)
2) Отпустите мьютекс.

Другие вопросы по тегам