2010-02-21 2 views
1

Это проблема чтения-записи для простой согласованности чтения. Вот алгоритм:Чтение - мьютексы писателя

void reader() { 
    while (1) { 
     P(mutex); 
     rc++; 
     if (rc == 1) P(db); /* <---- A */ 
     V(mutex); /* <---- B */ 
     read_data_base(); 
     P(mutex); 
     rc--; 
     V(mutex); 
     if (rc == 0) V(db); 
    } 
} 

void writer() { 
    while (1) { 
     P(db); 
     write_data_base(); 
     V(db); 
    } 
} 

Вот мои вопросы: 1. Какова цель линии А в коде чтения? 2. Если мы устраним эту строку, код будет работать правильно?

ответ

3
  • Целью строки A является проверка, является ли текущий считыватель первым после записи (или первого в целом). Если это так, то он должен получить мьютекс базы данных (db), чтобы ни один писатель не мог писать в базу данных, хотя есть хотя бы один читатель, читающий его.

    Соответствующая строка для последнего читателя:

    if (rc == 0) V(db);

    Цель этой линии, чтобы проверить, если текущий читатель последний читатель, так что автор может ввести следующий (если не является другим читателем, который входит перед писателем).

  • Основываясь на приведенном выше описании, если вы устраните строку A, ваш код будет работать неправильно.

Примечание: Как видно в ответ Влада ниже (и обсуждение в их комментарии), V(mutex) должны быть после if (rc == 0) V(db).

1

Прежде всего, код неправильный: вам необходимо выполнить if (rc ==0) V(db) под замком mutex.

Строка A необходима для блокировки базы данных для чтения. Блокировка устанавливается при первом чтении и освобождается после последнего; а также устанавливается во время каждой из возможных операций записи. Если блокировка не будет установлена, операция чтения и записи может выполняться одновременно, что приводит к повреждению данных.

+0

Вы уверены, что код не правильный? Можете ли вы привести пример, где произошла ошибка? – 3lectrologos

+0

Я также думаю, что это неправильно .. thread 1: // Предположим, rc == 0 V (мьютексы); переключатель в резьбу 2: P (мьютексы); rC++; // now rc == 1 переключатель в нить 1: if (rc == 0) V (db); // rc уже 1, поэтому он забывает V (db). – stmax

+0

Конечно. Представьте, что читатель № 1 входит в поток # 1 и выполняет до строки 'if (rc == 0) V (db);' (но не включая его). Теперь контекст переключается на поток # 2. В потоке # 2 приходит другой читатель, блокирует мьютекс, увеличивает «rc», теперь значение «rc» равно 2. Поэтому второй считыватель не блокирует 'db'. Теперь контекст переключается на поток # 3, в этом потоке автор пытается заблокировать db, получает блокировку и изменяет данные, которые в настоящее время считываются потоком # 2. Таким образом, данные будут повреждены. – Vlad

0

Писатель не должен писать, пока кто-то читает. Поэтому любой читатель блокирует db, когда он читает, если он является ранней птицей (№ 1). И он должен очистить блокаду, если он последний парень в комнате (rc == 0).

Смежные вопросы