Russian Qt Forum
Ноябрь 26, 2024, 16:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Потокобезопасность простой операции  (Прочитано 10463 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Декабрь 02, 2009, 20:52 »

Добрый вечер

Прошу прощения если вопрос глупый, может просто устал переделывая задачу для всех процессоров.
Выполняется очень простая операция.
Код:
theSum.red += сolor.red;
theSum - общий, доступен всем ниткам. сolor свой у каждой нитки (локальная переменная). Члены классов red - оба float

Вопрос: это thread-safe ("потокобезопасно") или нет? (мое мнение "нет").

Спасибо
Записан
niXman
Гость
« Ответ #1 : Декабрь 02, 2009, 21:09 »

Не безопасно!
А тем более что речь идет о нескольких платформах.
Эта операция находится в функции? Покажите ее.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Декабрь 02, 2009, 21:24 »

Не безопасно!
А тем более что речь идет о нескольких платформах.
Эта операция находится в функции? Покажите ее.
Ну "дословно" показывать никакой ясности не внесет, а смысл такой

Цитировать
struct ARGB {
  float alpha, red, green, blue;
};

ARGB theSum;  // глобальная переменная
....

void ThreadFunc( void * )   // рабочая ф-ция нитки
{
  ...
  ARGB color;
  EvalColor(&color);
  ...
  theSum.red += color.red;
  ...
}
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #3 : Декабрь 02, 2009, 22:00 »

Несильно в этом понимаю, но, а что если написать volatile перед ARGB theSum? Вроде как компилер, должен теперь боятся её изменения "вдруг" и прнимать спецмеры.
Записан

Юра.
niXman
Гость
« Ответ #4 : Декабрь 02, 2009, 23:29 »

Код
C++ (Qt)
struct ARGB {
 QMutex mutex;
 float alpha, red, green, blue;
};
 
ARGB theSum;  // глобальная переменная
....
 
void ThreadFunc( void * )   // рабочая ф-ция нитки
{
 ...
 ARGB color;
 EvalColor(&color);
 ...
 theSum.mutex.lock();
 theSum.red += color.red;
 theSum.mutex.unlock();
 ...
}
 
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #5 : Декабрь 03, 2009, 00:25 »

а что если написать volatile перед ARGB theSum?

Это оградит от оптимизации, а не от параллельного доступа.
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #6 : Декабрь 03, 2009, 00:54 »

Цитировать
а не от параллельного доступа.
почему?
Записан

Юра.
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #7 : Декабрь 03, 2009, 01:35 »

Цитировать
а не от параллельного доступа.
почему?

потому что volatile - это compile-time вещь, а доступ к переменным - run-time. Ты не можешь в compile-time гарантировать (без локов), что переменная запишется корректно при доступе из разных потоков. Алёна немного писала про это http://alenacpp.blogspot.com/2006/04/volatile.html
Записан
spectre71
Гость
« Ответ #8 : Декабрь 03, 2009, 08:07 »

Код
C++ (Qt)
...
 

Немножко не так. QMutex неимоверно дорогой для простейших операций.

Код
C++ (Qt)
struct ARGB {
 float alpha, red, green, blue;
 inline void lock    (void) {while (!mutex.testAndSetAcquire(0, 1));}
 inline void unlock  (void) {mutex.testAndSetRelease(1, 0);)
private:
 QAtomicInt mutex;
};
 
ARGB theSum;  
....
 
void ThreadFunc( void * )  
{
 ...
 ARGB color;
 EvalColor(&color);
 ...
 theSum.lock();
 theSum.red += color.red;
 theSum.unlock();
 ...
}
 

Или так

Код
C++ (Qt)
struct ARGB {
 float alpha, red, green, blue;
};
 
struct SimpleLocker {
 inline void lock    (void) {while (!mutex.testAndSetAcquire(0, 1));}
 inline void unlock  (void) {mutex.testAndSetRelease(1, 0);)
private:
 QAtomicInt mutex;
};
 
ARGB theSum;  
SimpleLocker SumMutex;
....
 
void ThreadFunc( void * )  
{
 ...
 ARGB color;
 EvalColor(&color);
 ...
 SumMutex.lock();
 theSum.red += color.red;
 SumMutex.unlock();
 ...
}
 
« Последнее редактирование: Декабрь 03, 2009, 08:12 от Spectre » Записан
BRE
Гость
« Ответ #9 : Декабрь 03, 2009, 08:41 »

Процессор же кушать будет? Не?
Код
C++ (Qt)
while (!mutex.testAndSetAcquire(0, 1));
Записан
spectre71
Гость
« Ответ #10 : Декабрь 03, 2009, 09:02 »

Процессор же кушать будет? Не?
Код
C++ (Qt)
while (!mutex.testAndSetAcquire(0, 1));


Будет! Для представленной задачи подходит, в типичной ситуации(когда кто-то уже заблокировал, очень редкая в данном случае) крутимся в цикле очень не долго(несколько итераций цикла).

Вообще-то все нормальные реализации Mutex (в QT не нормальный) устроены так:
Попытка заблокировать:
1) Крутимся на атоме N раз но не меньше 1 (N задается в конструкторе мьютекса или в методе lock,  может быть и 0) - очень дешево
Если не заблокировали
2) Дальше устанавливаем сигнал и перходим в спячку - очень дорого
3) Просыпаемся по сигналу - очень дорого

В QT - так:
1) Проверяем атом 1 раз
Если не заблокировали
2) Дальше устанавливаем сигнал и перходим в спячку - очень дорого
3) Просыпаемся по сигналу - очень дорого
Записан
niXman
Гость
« Ответ #11 : Декабрь 03, 2009, 09:06 »

Цитировать
Немножко не так. QMutex неимоверно дорогой для простейших операций.
Ну раз уж на то пошло, то нужно использовать WriteLock. Чтоб для операций чтения блокировка вообще не использовалась Показает язык
Записан
spectre71
Гость
« Ответ #12 : Декабрь 03, 2009, 09:13 »

Цитировать
Немножко не так. QMutex неимоверно дорогой для простейших операций.
Ну раз уж на то пошло, то нужно использовать WriteLock. Чтоб для операций чтения блокировка вообще не использовалась Показает язык

Только для Int и для замены указаталя Улыбающийся
А в данном случае float!
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Декабрь 03, 2009, 12:06 »

Спасибо за ответы. Как я понял, все считают что начальный текст НЕ потокобезопасен. Бог с ними с  определениями, хотелось бы узнать: чем мне это гроэит? Я завалю нитку? Вылечу? Разумеется я обнуляю theSum перед запуском ниток и читаю ее только после того как все нитки завершены (в нитках только добавляю в нее).

Другими словами, во что выльется неудобоваримое "непотокобезопасно!"?
Записан
BRE
Гость
« Ответ #14 : Декабрь 03, 2009, 12:33 »

Другими словами, во что выльется неудобоваримое "непотокобезопасно!"?
В неправильное значение theSum, только и всего.  Улыбающийся
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.241 секунд. Запросов: 23.