Название: Потокобезопасность простой операции Отправлено: Igors от Декабрь 02, 2009, 20:52 Добрый вечер
Прошу прощения если вопрос глупый, может просто устал переделывая задачу для всех процессоров. Выполняется очень простая операция. Код: theSum.red += сolor.red; Вопрос: это thread-safe ("потокобезопасно") или нет? (мое мнение "нет"). Спасибо Название: Re: Потокобезопасность простой операции Отправлено: niXman от Декабрь 02, 2009, 21:09 Не безопасно!
А тем более что речь идет о нескольких платформах. Эта операция находится в функции? Покажите ее. Название: Re: Потокобезопасность простой операции Отправлено: Igors от Декабрь 02, 2009, 21:24 Не безопасно! Ну "дословно" показывать никакой ясности не внесет, а смысл такойА тем более что речь идет о нескольких платформах. Эта операция находится в функции? Покажите ее. Цитировать struct ARGB { float alpha, red, green, blue; }; ARGB theSum; // глобальная переменная .... void ThreadFunc( void * ) // рабочая ф-ция нитки { ... ARGB color; EvalColor(&color); ... theSum.red += color.red; ... } Название: Re: Потокобезопасность простой операции Отправлено: lit-uriy от Декабрь 02, 2009, 22:00 Несильно в этом понимаю, но, а что если написать volatile перед ARGB theSum? Вроде как компилер, должен теперь боятся её изменения "вдруг" и прнимать спецмеры.
Название: Re: Потокобезопасность простой операции Отправлено: niXman от Декабрь 02, 2009, 23:29 Код
Название: Re: Потокобезопасность простой операции Отправлено: Alex Custov от Декабрь 03, 2009, 00:25 а что если написать volatile перед ARGB theSum? Это оградит от оптимизации, а не от параллельного доступа. Название: Re: Потокобезопасность простой операции Отправлено: lit-uriy от Декабрь 03, 2009, 00:54 Цитировать а не от параллельного доступа. почему?Название: Re: Потокобезопасность простой операции Отправлено: Alex Custov от Декабрь 03, 2009, 01:35 Цитировать а не от параллельного доступа. почему?потому что volatile - это compile-time вещь, а доступ к переменным - run-time. Ты не можешь в compile-time гарантировать (без локов), что переменная запишется корректно при доступе из разных потоков. Алёна немного писала про это http://alenacpp.blogspot.com/2006/04/volatile.html Название: Re: Потокобезопасность простой операции Отправлено: spectre71 от Декабрь 03, 2009, 08:07 Код
Немножко не так. QMutex неимоверно дорогой для простейших операций. Код
Или так Код
Название: Re: Потокобезопасность простой операции Отправлено: BRE от Декабрь 03, 2009, 08:41 Процессор же кушать будет? Не?
Код
Название: Re: Потокобезопасность простой операции Отправлено: spectre71 от Декабрь 03, 2009, 09:02 Процессор же кушать будет? Не? Код
Будет! Для представленной задачи подходит, в типичной ситуации(когда кто-то уже заблокировал, очень редкая в данном случае) крутимся в цикле очень не долго(несколько итераций цикла). Вообще-то все нормальные реализации Mutex (в QT не нормальный) устроены так: Попытка заблокировать: 1) Крутимся на атоме N раз но не меньше 1 (N задается в конструкторе мьютекса или в методе lock, может быть и 0) - очень дешево Если не заблокировали 2) Дальше устанавливаем сигнал и перходим в спячку - очень дорого 3) Просыпаемся по сигналу - очень дорого В QT - так: 1) Проверяем атом 1 раз Если не заблокировали 2) Дальше устанавливаем сигнал и перходим в спячку - очень дорого 3) Просыпаемся по сигналу - очень дорого Название: Re: Потокобезопасность простой операции Отправлено: niXman от Декабрь 03, 2009, 09:06 Цитировать Немножко не так. QMutex неимоверно дорогой для простейших операций. Ну раз уж на то пошло, то нужно использовать WriteLock. Чтоб для операций чтения блокировка вообще не использовалась :PНазвание: Re: Потокобезопасность простой операции Отправлено: spectre71 от Декабрь 03, 2009, 09:13 Цитировать Немножко не так. QMutex неимоверно дорогой для простейших операций. Ну раз уж на то пошло, то нужно использовать WriteLock. Чтоб для операций чтения блокировка вообще не использовалась :PТолько для Int и для замены указаталя :) А в данном случае float! Название: Re: Потокобезопасность простой операции Отправлено: Igors от Декабрь 03, 2009, 12:06 Спасибо за ответы. Как я понял, все считают что начальный текст НЕ потокобезопасен. Бог с ними с определениями, хотелось бы узнать: чем мне это гроэит? Я завалю нитку? Вылечу? Разумеется я обнуляю theSum перед запуском ниток и читаю ее только после того как все нитки завершены (в нитках только добавляю в нее).
Другими словами, во что выльется неудобоваримое "непотокобезопасно!"? Название: Re: Потокобезопасность простой операции Отправлено: BRE от Декабрь 03, 2009, 12:33 Другими словами, во что выльется неудобоваримое "непотокобезопасно!"? В неправильное значение theSum, только и всего. :)Название: Re: Потокобезопасность простой операции Отправлено: spectre71 от Декабрь 03, 2009, 12:34 Спасибо за ответы. Как я понял, все считают что начальный текст НЕ потокобезопасен. Бог с ними с определениями, хотелось бы узнать: чем мне это гроэит? Я завалю нитку? Вылечу? Разумеется я обнуляю theSum перед запуском ниток и читаю ее только после того как все нитки завершены (в нитках только добавляю в нее). Другими словами, во что выльется неудобоваримое "непотокобезопасно!"? В результате "гонок": a) можно получить "мусор" в theSum.red b) можно считать не правильное значение из theSum.red Название: Re: Потокобезопасность простой операции Отправлено: Alp от Декабрь 03, 2009, 12:50 x += y раскрывается в x = x+y
Для двух потоков: 1. Поток0: Вычисляется x + y0 (=x') 2. Поток1: Вычисляется x + y1 (=x'') 3. Поток0: x = x' 4. Поток1: x = x'' В итоге теряется первое присвоение. Я не в курсе что там насчет атомарности суммирования флоатов, может и в них ошибка набежать. Название: Re: Потокобезопасность простой операции Отправлено: Igors от Декабрь 03, 2009, 13:27 x += y раскрывается в x = x+y Это правильно "по существу" но код в обоих случаях разный (это не макрос который раскрывается)Происходит следующее 1) theSum.red и color.red принимаются на регистры (может только theSum.red) 2) выполняется сложение, результат в регистре 3) содержимое регистра записывается в theSum.red Если не принимать мер, это не работает правильно с 2-мя и более нитками, т.к. др. нитка может "вклиниться" между 1 и 3. Я выбрал такой способ решения (за счет усложнения кода) Код: struct ARGB { Название: Re: Потокобезопасность простой операции Отправлено: lit-uriy от Декабрь 03, 2009, 16:44 >>x += y раскрывается в x = x+y
как сказал Igors, это просто логическое раскрытие. Это самостоятельный оператор. Посмотри описание классов Qt API, в некоторых увидишь перегрузку такого оператора "+=" (или подобного, например "&="). |