Данные, многопоточность, синхронизация.
От: User99  
Дата: 14.02.02 13:34
Оценка:
Ситуация следующая:
Имеется массив объектов(несколько тысяч). Каждый объект находится каком-то состоянии(3-10 состояний),
3 рабочих потока пользуются этим массивом. Каждый рабочий может смотреть и изменять
состояния объектов. +Имеется еще и интерфейсный поток(пока только просмотр состояний
объектов). Разумеется необходима синхронизация.
1.Одна Критическая секция для всего массива.
Минусы — читает только один все остальные ждут.
2.Два события для всего массива (одно для читателей другое для писателей) читают все одновременно,
пишет только 1.
Минусы — Пишущий поток по прежнему блокирует массив.

3. Вариант 2, но для каждого экземпляра.
Помоему так недьзя(количество HANDLOV у ОС конечно).

4.

class O
{
public:
      //какие-то данные
protected:
    bool        m_bRead;
    bool        m_bWrite;
    static HANDLE    m_Update;
public:
       LockRead()
    {
     for(;m_bRead;)//пока занято
     {
            WaitForSingleObject(m_Update,-1);
        ResetEvent(m_Update);
         }
         m_bRead=true;
     }
      UnLockRead()
      {
     m_bRead=false;
        SetEvent(m_Update);
      }
   //Для записи аналогично
}

vector<O> vO;
Ваше мнение по поводу всего этого. Повторюсь размер массива 1000-60000;
Re: Данные, многопоточность, синхронизация.
От: User99  
Дата: 14.02.02 13:51
Оценка:
U> LockRead()
U> {
U> for(;m_bRead//пока занято
U> {
U> WaitForSingleObject(m_Update,-1);
U> ResetEvent(m_Update);
U> }
U> m_bRead=true;
U> }
Так наверное правильнее
LockRead()
{
for(;m_bRead//пока занято
WaitForSingleObject(m_Update,-1);
m_bRead=true;
}
Re: Данные, многопоточность, синхронизация.
От: yogi Россия  
Дата: 14.02.02 13:52
Оценка: 1 (1)
Здравствуйте User99,

Есть у меня предложение... Не блестящее, конечно... Я бы попроюовал что-то среднее между пунктами 1 и 3, т.е. организовал бы семафорчик для каждой 100(1000) элементов. Тогда, если потоки работают с массивом "вразнобой", это может быть разумным компромисом...
Путь к сердцу женщины лежать не должен.
Re[2]: Данные, многопоточность, синхронизация.
От: User99  
Дата: 14.02.02 13:59
Оценка:
Здравствуйте yogi, Вы писали:

Y>Здравствуйте User99,


Y>Есть у меня предложение... Не блестящее, конечно... Я бы попроюовал что-то среднее между пунктами 1 и 3, т.е. организовал бы семафорчик для каждой 100(1000) элементов. Тогда, если потоки работают с массивом "вразнобой", это может быть разумным компромисом...


Спасибо Интересует также мнение насчет приведенного варианта.
Re: Данные, многопоточность, синхронизация.
От: User99  
Дата: 14.02.02 14:08
Оценка:
Извините за ошибку. Правильно будет так

    LockRead()
    {
        for(;m_bWrite;)
            WaitForSingleObject(m_hUpdate,-1);
        m_bRead=true;
    }
    UnlockRead()
    {
        m_bRead=false;
        ResetEvent(m_hUpdate);
    }
    LockWrite()
    {
        for(;m_bWrite || m_bRead;)
            WaitForSingleObject(m_hUpdate,-1);
        m_bWrite=true;
    }
    UnLockWrite()
    {
        m_bWrite=false;
        ResetEvent(m_hUpdate);
    }
Re: Данные, многопоточность, синхронизация.
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 14.02.02 16:39
Оценка:
U>Повторюсь размер массива 1000-60000;

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

Массив, наверное, во время работы может менять размеры?

Вообщем, клёвая задача.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Данные, многопоточность, синхронизация.
От: Lafkadio Россия  
Дата: 14.02.02 18:52
Оценка:
Здравствуйте User99, Вы писали:
U>Ваше мнение по поводу всего этого. Повторюсь размер массива 1000-60000;

Думаю что Вам может помочь семейтсво функций Interlocked:


LONG InterlockedExchangeAdd(PLONG plAddend, LONG lIncrement);

Добавление величины
Рихтер пишет, что она гарантирует приращение значения переменной
на уровне атомарного доступа,
т.е. без прерывания другими потоками


LONG  InterlockedExchange(PLONG plTarget, LONG lValue);

замещение величины


PVOID IntelockedExchangePointer(PVOID* ppvTarget, PVOID pvValue);


А чтение как обычно..
Re: Данные, многопоточность, синхронизация.
От: Аноним  
Дата: 15.02.02 07:05
Оценка:
Здравствуйте User99, Вы писали:

U>Ситуация следующая:

U>Имеется массив объектов(несколько тысяч). Каждый объект находится каком-то состоянии(3-10 состояний),
U>3 рабочих потока пользуются этим массивом. Каждый рабочий может смотреть и изменять
U>состояния объектов. +Имеется еще и интерфейсный поток(пока только просмотр состояний
U>объектов). Разумеется необходима синхронизация.
U>1.Одна Критическая секция для всего массива.
U> Минусы — читает только один все остальные ждут.
U>2.Два события для всего массива (одно для читателей другое для писателей) читают все одновременно,
U>пишет только 1.
U> Минусы — Пишущий поток по прежнему блокирует массив.

U>3. Вариант 2, но для каждого экземпляра.

U> Помоему так недьзя(количество HANDLOV у ОС конечно).

Если я не ошибаюсь, то можно создать семафоры, которые будут иметь по Handle на поток и небольшую структуру на каждый блокируемый элемент. При этом читать могут несколько потоков (shared access), а читать/писать один (exclusive access).
U>4.

U>
U>class O
U>{
U>public:
U>      //какие-то данные
U>protected:
U>    bool        m_bRead;
U>    bool        m_bWrite;
U>    static HANDLE    m_Update;
U>public:
U>       LockRead()
U>    {
U>     for(;m_bRead;)//пока занято
U>     {
U>            WaitForSingleObject(m_Update,-1);
U>        ResetEvent(m_Update);
U>         }
U>         m_bRead=true;
U>     }
U>      UnLockRead()
U>      {
U>     m_bRead=false;
U>        SetEvent(m_Update);
U>      }
U>   //Для записи аналогично
U>}
U>

U>vector<O> vO;
U>Ваше мнение по поводу всего этого. Повторюсь размер массива 1000-60000;
Re: Данные, многопоточность, синхронизация.
От: Vogul  
Дата: 15.02.02 07:48
Оценка:
Здравствуйте User99, Вы писали:

Мне кажется, что в данном случае надо организовать синхронизацию не на уровне элементов массива(вариант 3), а на уровне читателей-писателей, т. е. объекты синхронизации создаются не для каждого элемента массива, а для каждого читателя-писателя(ведь именно их и надо разделить). При обращению к элементу проверять, не занят ли он кем, если занят, то ждать освобождения. А заботу о сигнализации освобождения элемента возложить на того, кто его занял. Получится некий массив: кто занял и что занял.
Re[2]: Данные, многопоточность, синхронизация.
От: Ivan Россия www.rsdn.ru
Дата: 15.02.02 08:11
Оценка:
Здравствуйте Vogul, Вы писали:

V>Здравствуйте User99, Вы писали:


V>Мне кажется, что в данном случае надо организовать синхронизацию не на уровне элементов массива(вариант 3), а на уровне читателей-писателей, т. е. объекты синхронизации создаются не для каждого элемента массива, а для каждого читателя-писателя(ведь именно их и надо разделить). При обращению к элементу проверять, не занят ли он кем, если занят, то ждать освобождения. А заботу о сигнализации освобождения элемента возложить на того, кто его занял. Получится некий массив: кто занял и что занял.


Есть недокументированные функции Windows NT для блокировки "Читатель/Писатель". О них написано в "Windows Developer's Journal" Jan 99. С сайта журнала можно скачать архив с С++ кодом: ftp://ftp.wdj.com/pub/1999/jan99.zip (нужный файл называется claar.zip).

Еще блокировка "Читатель/Писатель" описана в книжке "Designing solutions with COM+ Technologies".
Re: Данные, многопоточность, синхронизация.
От: Sinclair Россия https://github.com/evilguest/
Дата: 19.02.02 15:48
Оценка: 5 (2)
Это очень похоже на базу данных:
Есть длинная (1000-60000 записей) таблица; несколько клиентов читают/пишут различные записи.
Сервера, построенные на pessimistic locking, типа MS SQL, создают специальные объекты "lock" — это некоторый аналог синхронизационных объектов операционной системы. Для того, чтобы оптимизировать количество локов, они используют переменную гранулярность. Т.е. лок может быть поставлен на отдельную запись, страницу (несколько записей, идущих друг за другом), или всю таблицу.
Вообще говоря, количество локов, поставленных одновременно, зависит от количества одновременных транзакций и от их "длины", т.е. количества изменяемых элементов.
Смысл в том, что локи создаются динамически, т.е. нет предопределенных объектов, созданных для каждой записи. Лок менеджер управляет доступом к данным и "раздает" их динамически. В твоем случае имеет смысл сделать вторичную структуру, которая описывает "залоченность" объектов, и прогонять все операторы доступа через нее. Тогда будет один постоянный синхронизационный объект — на вторичную структуру, а она, в свою очередь, будет динамически использовать необходимое количество синхронизационных объектов для управления доступом к основным данным. Если у тебя каждая транзакция читает/записывает только один объект, то не надо никакой гранулярности, а количество этих локов будет равно количеству потоков, независимо от размера данных (количества объектов)
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Данные, многопоточность, синхронизация.
От: User99  
Дата: 19.02.02 16:05
Оценка:
Выводы сделал. Всем спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.