2010-03-09 5 views
13

Я использую блокировки чтения/записи в Linux, и я обнаружил, что пытается обновить заблокированный объект до блокировок блокировки записи.pthreads: блокировки чтения/записи, обновление блокировки чтения для записи блокировки

т.е.

// acquire the read lock in thread 1. 
pthread_rwlock_rdlock(&lock); 

// make a decision to upgrade the lock in threads 1. 
pthread_rwlock_wrlock(&lock); // this deadlocks as already hold read lock. 

Я прочитал страницу человека, и это вполне конкретны.

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

Каков наилучший способ обновления блокировки чтения блокировки записи в этих обстоятельствах. Я не хочу вводить гонку за переменную, которую я защищаю.

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

Thx

+0

Boost.Thread имеет концепцию UpgradeLockable, но я сомневаюсь, что это очень полезно для вас, если ваш код уже проложен в pthreads. –

+0

@Steve. Вы знаете, как это реализовано. Использует ли он отдельный мьютекс, который я рассматривал? Я полагаю, я мог бы скачать его и проверить: o) – ScaryAardvark

+0

Нет, я не знаю, как Boost.Thread это делает, извините. –

ответ

15

Что еще, кроме мертвой блокировки, вы хотите в следующем сценарии?

  • нить 1 приобретают прочитать замок
  • нить 2 приобретают прочитать замок
  • нить 1 попросить обновить замок, чтобы написать
  • нить 2 попросить обновить замок, чтобы написать

Так что я d просто отпустите блокировку чтения, приобретите блокировку записи и еще раз проверьте, должен ли я сделать обновление или нет.

+0

Почему один из потоков получает блокировку записи, если другой удерживает блокировку чтения? И если оба в конечном итоге могут получить блокировку записи, вторая проблема будет связана с тем, что все сделанные проверки должны быть переделаны, так как защищенный ресурс может быть значительно изменен. Таким образом, освобождение и повторная схватка обеспечивают такое же поведение. – AProgrammer

+0

Я надеялся избежать второй проверки блокировки объекта. Я знаю, что внедрение IBM блокировок чтения/записи позволяет вызывающему потоку обновлять его блокировку, если это единственный поток, содержащий блокировку записи. http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=/apis/users_93.htm – ScaryAardvark

+0

@nos. Да, это будет тупик. T1 при запросе обновления будет заблокирован, так как T2 имеет блокировку чтения. Затем T2 блокируется при обновлении для записи блокировки, поскольку T1 содержит блокировку чтения. – ScaryAardvark

0

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

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

+2

Кажется немного сверху, чтобы получить блокировку записи, когда вам это может понадобиться. Как вы указали, это будет сериализоваться. В то время как приобретение блокировки чтения не блокируется. В тот момент, когда вы знаете, что вам нужно что-то изменить, вы можете перейти на блокировку записи. Это просто фактический акт, сделанный таким образом, под позицией, представляет гонку, что является позором. – ScaryAardvark

+0

Это позор, но в большинстве случаев я знаю, это скорее теоретическая разница. – stefaanv

0

Я думаю, вместо использования блокировки чтения/записи pthread вы можете использовать Posix fcntl(). Здесь вы можете обновиться от чтения, чтобы писать без каких-либо проблем. Мы используем его для вставки B-дерева. Как только мы узнаем узел, где происходит вставка, мы обновим его, чтобы записать блокировку. Также, когда нам нужно разделить узел, мы обновим блокировку узла, его родительского узла и детей от чтения до записи. Поскольку B-tree - это структура данных на основе файлов, это помогает блокировать область файла.

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