Синхронизация доступа к std::list<> (Требуется совет братиев во программировании :))

Модератор: Модераторы разделов

Аватара пользователя
Zeus
Сообщения: 694

Синхронизация доступа к std::list<>

Сообщение Zeus »

Есть std::list<...>.
К нему обращаются несколько потоков на чтение и один на модификацию (добавление-удаление).
Задача:
- потоки на чтения друг друга блокировать не должны, но должны блокировать поток модификации.
- если поток модификации начал обработку списка, то должны блокироваться потоки чтения.

У меня пока одна версия как это сделать.
Завести два мьютекса: mutexRead и mutexWrite.
Поток модификации просто запирает (или блокируется) оба мьютекса последовательно - или заблокируется на одном из них или заблокирует потоки чтения на muteWrite.
Потоки чтения тоже работают с двумя мьютексами, но по другому:
- запирают mutexWrite без блокировки (trylock). Если он уже был заперт, то лочатся на нём (типа, лист модифицируется). После разблокирования потока - делают свои дела со списком и разлочат mutexWrite.
- запирают mutexRead без блокировки (trylock). Делают свои дела со списком. Если mutexRead не был заперт на входе, то отпирают.

Тяжело читать да? Какое-то некрасивое решение, громоздко... Короче не нравится мне.
Может кто-то другое посоветует по мотивам первого абзаца (условие задачи)?
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Синхронизация доступа к std::list<>

Сообщение oav »

Могу дать рихторовский класс где весьма неплохо реализована задача Single writer multiple reader guard. Только он для Win32 но переделать не составит труда.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Синхронизация доступа к std::list<>

Сообщение Zeus »

oav писал(а):
03.02.2006 11:25
Могу дать рихторовский класс где весьма неплохо реализована задача Single writer multiple reader guard. Только он для Win32 но переделать не составит труда.

А что он их себя представляет?
Хотя ладно, давай зашли на z e u s АУ-АУ crtc. spb. ru
Посмотрю что там.
Спасибо.
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Синхронизация доступа к std::list<>

Сообщение oav »

Zeus писал(а):
03.02.2006 11:28
oav писал(а):
03.02.2006 11:25

Могу дать рихторовский класс где весьма неплохо реализована задача Single writer multiple reader guard. Только он для Win32 но переделать не составит труда.

А что он их себя представляет?
Хотя ладно, давай зашли на z e u s АУ-АУ crtc. spb. ru
Посмотрю что там.
Спасибо.

Ушло. Вполне простая и универсальная конструкция. Пишеться один раз, попадает в некий BaseLib и юзается долго
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Синхронизация доступа к std::list<>

Сообщение v04bvs »

Zeus писал(а):
03.02.2006 10:56
Есть std::list<...>.
К нему обращаются несколько потоков на чтение и один на модификацию (добавление-удаление).
Задача:
- потоки на чтения друг друга блокировать не должны, но должны блокировать поток модификации.
- если поток модификации начал обработку списка, то должны блокироваться потоки чтения.

У меня пока одна версия как это сделать.
Завести два мьютекса: mutexRead и mutexWrite.
Поток модификации просто запирает (или блокируется) оба мьютекса последовательно - или заблокируется на одном из них или заблокирует потоки чтения на muteWrite.
Потоки чтения тоже работают с двумя мьютексами, но по другому:
- запирают mutexWrite без блокировки (trylock). Если он уже был заперт, то лочатся на нём (типа, лист модифицируется). После разблокирования потока - делают свои дела со списком и разлочат mutexWrite.
- запирают mutexRead без блокировки (trylock). Делают свои дела со списком. Если mutexRead не был заперт на входе, то отпирают.

Тяжело читать да? Какое-то некрасивое решение, громоздко... Короче не нравится мне.
Может кто-то другое посоветует по мотивам первого абзаца (условие задачи)?


Это классическая задача синхронизации, поищите в сети алгоритм. Если надо - я попробую написать.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Синхронизация доступа к std::list<>

Сообщение Zeus »

v04bvs писал(а):
03.02.2006 14:19
Это классическая задача синхронизации, поищите в сети алгоритм. Если надо - я попробую написать.

Да мне алгоритм не нужен - хватит и ИДЕИ. Красивой только, идеи. А уж реализовать-то - дело техники.
Может у кого есть оригинальное решение (классическое/неклассическое - неважно), описываемое парой предложений.
Спасибо сказали:
v04bvs
Сообщения: 636
ОС: Debian GNU/Linux

Re: Синхронизация доступа к std::list<>

Сообщение v04bvs »

В общем алгоритм на псевдоСи, использует общие семафоры и одну общую переменную.
int rc = 0; //количество читателей
semaphore sw = 1; //семафор на запись
semaphore st = 1; //вспомогательный семафор

Код: Выделить всё

//читатель
void reader( )
{
    // цикл чтения
    while( 1 ) {
        // входим в блок чтения
        down(&st);
        if( rc++ == 0 )  //если это первый процесс-читатель
          down(&sw);       // запрещаем запись (или ждём пока писатель освободит семафор)
        up(&st);

        do_read_operation(); //производим все необходимые действия

        // выходим из блока чтения
        down(&st);
        if( --rc == 0 ) //если это последний процесс-читатель
          up(&sw);
        up(&st);
    }
}

// писатель
void writer( )
{
    while( 1 ) {
        down(&sw);
        do_write_operation();
        up(&sw);
    }
}



down, up - опустить, поднять семафор.
Используя SystemV IPC можно обойтись и без дополнительной общей переменной (думаю понятно, как это сделать).

У этого алгоритма есть один недостаток - писатель не получит доступа к ресурсу до того момента, пока все читатели не освободят ресурс.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Синхронизация доступа к std::list<>

Сообщение Zeus »

oav - спасибо, класс получил. До подробного изучения руки ещё не дошли, но мельком посмотрел - сильно похоже на то, что написал v04bvs.

У этого алгоритма есть один недостаток - писатель не получит доступа к ресурсу до того момента, пока все читатели не освободят ресурс.

Это существенный недостаток.
У меня-то потоки равноправные: "кто первый встал - того и тапки", но нужно, чтобы потоки чтения друг друга не блокировали.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: Синхронизация доступа к std::list<>

Сообщение Zeus »

Короче, написал класс "по мотивам" постов и присланных файликов:
счётчики читателей-писателей, мьютекс и семафор.

Всем спасибо.
Спасибо сказали: