LINUX.ORG.RU

Исходники pthread_mutex_lock() и о блокировках вообще?


0

0

Такая проблема - нуна блокировка объекта обеспечиввающее совместное чтение и уникальную запись. На пионе. Я что то сделал, но возник вопрос, то ли, пполез копать исходники - концы ушли в so моудль, исходников к-го я что то не найду... но боюсь что они мне и не помогут:-)

Может кто подскажет, как реализовано это дело на пальцах? На флагах руками или средствами ОС специяльными? :-) И насколько допустимо в таки вопромах полагаться на свои флаги /счетчики, если работа с ними всыделена в CriticalSection?

Вот что на пионе получилось: class _locked: def __init__(self, *L, **D): self.lock, self.read_lock_counter = thread.allocate_lock(), 0 ..... def _run_under_read_lock(self, func, L, D) : self.lock.acquire() self.read_lock_counter += 1 self.lock.release() try: return apply(func, L, D) finally: self.read_lock_counter -= 1 def _run_under_full_lock(self, func, L, D) : self.lock.acquire() while self.read_lock_counter > 0 : pass try: return apply(func, L, D) finally: self.lock.release() .....

anonymous

Епрст...... еще раз:

class _locked:

def __init__(self, *L, **D):

self.lock, self.read_lock_counter = thread.allocate_lock(), 0

def _run_under_read_lock(self, func, L, D) :

self.lock.acquire()

self.read_lock_counter += 1

self.lock.release()

try: return apply(func, L, D)

finally: self.read_lock_counter -= 1

def _run_under_full_lock(self, func, L, D) :

self.lock.acquire()

while self.read_lock_counter > 0 : pass

try: return apply(func, L, D)

finally: self.lock.release()

anonymous
()
Ответ на: комментарий от anonymous

Как я понимаю тебе интересно, как можно реализовать объект доступ к которому на чтение могут получить сколько угодно потоков, но писатель может быть только один ?

Я в питоне не очень соображаю, но такую штуку делал как-то на С++ под Windows. Из "системных строительных блоков" понадобятся критические секции и желательно что-то типа c семафоров (чтоб умело отправлять процесс спать, пока не наступит некоторое событие, по-моему в pthreads есть mutex для таких дел).

Логика работы такая:

1) Каждый объект представляет ресурс который может читаться и в который могут записыватсья некоторая информация

2) с объектом связано 5 дополнительных полей: текущее число ждущих "читателей" (int waiting_readers), текущее число ждущих "писателей" (int waiting_writers), и счетчик потоков читающих из объекта (int used_by_readers) и пишуших (int used_by_writers) Помимо этого нужна одна критическая секция (cs), и читательский (rs) и писательский семафоры (ws).

access_for_read() { cs.lock();

bool cant_read=used_by_writer || waiting_writers >0;

if (cant_read) waiting_readres++; else used_by_reader++; cs.unlock();

if (cant_read) { rs.wait(); } }

read_done() { cs.lock() used_by_reader--;

if (used_by_reader==0 && wait_writers>0) { ws.wakeup(); waiting_writers--; used_by_writer=1; } cs.unlock() }

access_for_write() { cs.lock();

bool cant_write=used_by_reader || used_by_writer;

if (cant_write) waiting_writers++; else used_by_writer++; cs.unlock();

if (cant_write) { ws.wait(); } }

write_done() { cs.lock() used_by_writer--;

if (wait_writers>0) { ws.wakeup(); wait_for_writer--; used_by_writer++; } else if (wait_readers>0) { rs.wakeup(); used_by_reader++; waiting_readers--; }

cs.unlock() }

Примерно так ... если я не ошибся :)

ukez
()
Ответ на: комментарий от ukez

Да, формулировка правильная. Спасибо. Только как то поздно уже, спать хоцца... не разберу я, зачем так сложно, столько счетчиков?:-) Я сделал при помощи одной блокировки (крит. секции в общенпринятой терминологии наск я понимаю) и одного счетчика активных читателей.

Ну, раз на питоне не оч. понятно попробую на пальцах:

читатель пытается получить блокировку, и сразу ж ее возвращает, инкрементирует счетчик и начинает читать. После окончания чтения он счетчик декрементирует. Блокировку он получает что бы не начать читать пока кто то пишет, так она ему в общем не нужна, поскольку совместное чтение допустимо.

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

Работоспособно выглядит?

anonymous
()
Ответ на: комментарий от anonymous

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

Я там написал 5 счетчиков хотя реально их 4-ре: Счетчик ждущих читателей, счетчик ждущих чиатаелей, счетчик активных читателей, счетчик активных писателей. + 1 критическая секция + 2 семафора.

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

ukez
()
Ответ на: комментарий от ukez

Не, не будет. все вновь прибывающие читатели утыкаются в блокировку поднятую писателем и ждут ее освобождения. А те кто уже читают... но нужно же им дочитать.

anonymous
()
Ответ на: комментарий от ukez

Я просто не понял зачем столько счетчиков. Кто там чего ждет мне как то неинтересно, фиг с ними. Активных писателей м.б. токо один по определению. С-но кто остался.....

anonymous
()
Ответ на: комментарий от anonymous

В твоей проге уменьшать счетчик тоже надо в критической секции. скорее всего операция self.read_lock_counter-=1 не атомарная, может быть трабл с перезаписыванием :). Отсюда и начинаются проблемы с большим числом счетчиков. в идеале достаточно 3-х.

ukez
()
Ответ на: комментарий от ukez

Ну, я не знаю как в С++, но в питоне точно атомарная. Там нити за раз дают 10-15 инструкций байт-кода выполнить, и эта величина настраиваемая.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.