Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Синхронизировать или нет? 
:(
    Опции темы
ksili
Дата 26.10.2007, 08:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Вопрос такой. Программа создаёт несколько дочерних потоков. В основном потоке есть глобальная структура (даже массив структур). В каждый поток передается указатель на эту структуру. В процессе работы потоки к ней обращаются.
Надо ли синхронизировать такие обращения? Это же ведь не обращение к VCL... 
У меня пока синхронизированы (запихнуты в Synchronize) только изменения этой структуры из дочерних потоков. Надо ли ещё синхронизировать и чтения?


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Lazin
Дата 26.10.2007, 08:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



Через Synchronize нужно синхронизировать только те объекты которые используют очередь сообщений. Все глобальные объекты нужно синхронизировать по другому, например с помощью критических секций (TCriticalSection или API ф-ий). Иногда логика программы требует блокировки других потоков.
например

Код

CRITICAL_SECTION lock;
InitializeCriticalSection(&lock);


код потока

Код

EnterCriticalSection(&lock);
//используем глобальные данные
//одновременно этот участок кода может выполнять только 1 поток, остальные ждут
LeaveCriticalSection(&lock);


Другой пример, если один поток читает std::vector, а другой добавляет элементы в него то может произойти ошибка доступа (если произойдет realloc). В то-же время можно спокойно читать вектор из нескольких потоков.

Код

TMultiReadExclusiveWriteSynchronizer* lock;
std::vector<int> vect;

1 поток - читает
Код

lock->BeginRead();
for (std::vector<int>::iterator i = vect.begin(); i != vect.end(); ++i)
{
 делаем что-то что не меняет контейнер
}
lock->EndRead();


2 поток - добавляет
Код

for (;;)
{
 lock->BeginWrite();
 vect.push_back(somedata);
 lock->EndWrite();
}

здесь элемент в вектор добавлен не будет, пока не выполнится первый поток, в то-же время произвольное число потоков может читать вектор.
Еще один пример
Код

class Obj
{
bool flag;
public:

Obj() : flag(true) {}

void Method()//этот метод должен выполнить работу только один раз
{
 if (flag)
 {
  Сделать что-нибудь 1 раз
  flag = false;
 }
}
};

Представь что объект Obj используется несколькими потоками и оба вызывают метод Method, произойдет вот что:
оба потока проверят условие примерно в одно время, и flag == true для обоих
проблема решается критической секцией
Код

class Obj
{
bool flag;
CRITICAL_SECTION lock;

public:

Obj() : flag(true) {
  InitializeCriticalSection(&lock);
}

void Method()//этот метод должен выполнить работу только один раз
{
 EnterCriticalSection(&lock);
 if (flag)
 {
  Сделать что-нибудь 1 раз
  flag = false;
 }
 LeaveCriticalSection(&lock);
}
};

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

Это сообщение отредактировал(а) Lazin - 26.10.2007, 08:50
PM MAIL Skype GTalk   Вверх
ksili
Дата 26.10.2007, 08:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Спасибо за подсказку!
Изменения размера (realloc) у меня к счастью нет.
Цитата(Lazin @  26.10.2007,  13:35 Найти цитируемый пост)
EnterCriticalSection(&lock);
//используем глобальные данные
//одновременно этот участок кода может выполнять только 1 поток, остальные ждут
LeaveCriticalSection(&lock);

У меня нет кода, который может исполняться сразу несколькими потоками. У каждого потока "свои" функции. Даже если есть одинаковые. Но есть общие (глобальные) данные. В этом случае подойдёт ли использование критических секций для безопасного изменения этих данных?
Вот например в основном потоке глобальная структура g_All. В другом потоке есть указатель на неё: common = &g_All. Надо ли делать так:
Код

EnterCriticalSection(&lock);

//используем глобальные данные
common->chnls[i].used = true;

LeaveCriticalSection(&lock);
?


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Lazin
Дата 26.10.2007, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



Если структура содержит только POD то можно попробовать вообще без синхронизации, если что-то более сложное, то в структуру нужно добавить объект для синхронизации, и дергать данные не напрямую а через методы get/set.
PM MAIL Skype GTalk   Вверх
ksili
Дата 26.10.2007, 09:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Цитата(Lazin @  26.10.2007,  14:03 Найти цитируемый пост)
в структуру нужно добавить объект для синхронизации, и дергать данные не напрямую а через методы get/set

Где есть про это поподробнее? Или пример?

POD - это имелись в виду просто данные?

P.S. Почему здесь в коде C++Builder выделяется жирным слово lock. У меня в Билдере оно не выделяется...


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Lazin
Дата 26.10.2007, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 18
Всего: 154



Цитата(ksili @  26.10.2007,  09:06 Найти цитируемый пост)
POD
 Plain Old Data
Цитата(ksili @  26.10.2007,  09:06 Найти цитируемый пост)
Где есть про это поподробнее? Или пример?
tutorial

PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0534 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.