2016-05-02 2 views
-1

Я узнаю о потоках POSIX, и мой профессор начал учить о первой проблеме читателей-писателей. Это псевдокод, который я имею о решении проблемы (только для первого случая: предпочтение читателя).Как работают блокировки нескольких мьютексов?

semaphore rw_mutex = 1; /* semaphore common to both reader & writer */ 
semaphore mutex = 1; /* semaphore for reading (reader lock) */ 
int read_count = 0; /* track number of readers in CS */ 


Writer: 
do { 
lock(rw_mutex); 
/* ensure no writer or reader can enter */ 
... 
/* writing is performed */ 
... 
unlock(rw_mutex); 
/* release lock */ 
} while (true); 


Reader: 
do 
{ 
lock(mutex); 
/* first update read_count atomically */ 
read_count++; 
if (read_count == 1) { 
lock(rw_mutex); 
/* ensure no writer can enter */ 
} 
unlock(mutex); 
/* allow other readers to access */ 
... 
/* reading is performed */ 
... 
lock(mutex); 
read_count--;if (read_count == 0) unlock(rw_mutex); 
/* allow writers after 
last reader has left the CS */ 
unlock(mutex); 
/* release lock */ 
} while(true); 

Прежде всего, это мое понимание взаимных блокировок замков: После того, как мы создаем замок и разблокировать пару, код между этими двумя объектами может быть доступен только одним потоком одновременно.

Теперь, если мое понимание правильное, я могу в значительной степени понять, что происходит в разделе Writer вышеуказанного псевдокода. Мы блокируем, а затем записываем на общий ресурс, и тем временем никто не может получить доступ к общему ресурсу, так как он заблокирован, а затем мы просто разблокируем его.

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

Мой главный вопрос: Что означает блокировка? и в чем разница между словами lock (rw_mutex) и блокировкой (mutex) в вышеупомянутом псевдокоде? Если однажды мы назовем блокировку, программа должна заблокировать ее независимо от того, какой параметр мы передаем правильно? Итак, что здесь означают следующие параметры: rw_mutex и mutex? Как работает множественная блокировка мьютексов?

ответ

2

Способ думать о мьютексах выглядит так: мьютекс похож на токен, который в любой момент времени может удерживаться одним потоком или доступен для любого потока.

Когда поток вызывает lock() на мьютексе, он пытается принять мьютекс: если мьютекс доступен («разблокирован»), то он будет сразу, если он в настоящее время удерживается другим потоком (" заблокирован "), тогда он будет ждать, пока он не будет доступен.

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

Если у вас есть несколько мьютексов, каждый мьютекс независим: нить не может содержать ни одного, ни одного из них.

В вашей Reader нить сначала приобретает mutex. В то время как mutex принадлежит нити, никакой другой поток не может приобрести mutex, так что никакой другой поток не может быть выполнение между либо из lock(mutex);/unlock(mutex); пар (один в верхней части функции Reader и одного дальнейшего вниз). Поскольку read_count доступен только в такой паре (в то время как mutex), мы знаем, что только один поток будет получать доступ к read_count за раз.

Если Reader только что увеличил read_count от нуля до одного, он также приобретет мьютексы rw_mutex. Это предотвращает получение какой-либо другой нить , что мьютекс до тех пор, пока он не будет выпущен, что предотвратит переход Writer в его критический раздел.

Этот код эффективно передает право собственности на rw_mutex из потока, который запирал его в Reader любым остальным читателям в критическом разделе, когда эта нить выходит из критической секции.Это всего лишь вопрос логики кода - для этого не требуется никакого фактического вызова (и это возможно только потому, что он использует семафор для реализации rw_mutex, а не, например, mutex pthreads, который должен быть выпущен потоком, который заблокирован Это).