Какие ситуации могут вызвать исключения при выполнении доступа к данным из разных потоков? Наверное я разучился пользоваться поиском, но конкретного ответа не нашел. Interlocked функции делают безопасным запись данных из разных потоков, а как быть с остальными ситуациями типа чтение+чтение, чтение+выполнение чтение+запись одних и тех же данных? Или в этом случае исключение не будет вызвано? p.s. про спин-блокировки и крит секции знаю, просто хочу узнать, можно ли обойтись без них
Если выполняется в единый момент времени только чтение и/или выполнение то блокировка не нужна. Если запись есть еще в этот момент, то тогда всё надо по нормальному обернуть. Interlocked если нужно математические операции простые делать Иначе mutext и критические секции используй
У меня примерно так реализовано: volatile int var1; void potok1() { while(1) { if(var1) { //action... } } } void potok2() { while(1) { //...action int register result = //...action InterlockedExchange(&var1,result); } } т.е. второй поток пишет через Interlocked, а другой читает напрямую. Это обязательно оборачивать в крит секцию?
Чтобы не плодить тем, задам тут сразу еще один релевантный вопрос. Из-за потока, выполняющего в цикле операции с данными начинает тормозить основной поток, хотя я ему присвоил IDLE(-15) приоритет. Или этого не достаточно?
Простую запись в (выравненную по умолчанию) int var1 даже в Interlocked не обязательно оборачивать, не говоря уж о критсекции PS: Interlocked-операции нужны, когда нужно за один прием прочитать существующее значение и затем его изменить\переписать. А ты просто пишешь, и к тому же пишущий поток у тебя всего один
ок, спасибо. По поводу 2го вопроса. добавил отключение Priority Boost, в конце каждой итерации добавил SwitchToThread(); но должного эффекта нет, даже наоборот, чуть сильнее начал тормозить основной поток. Или же все таки нужно разбавить этот поток Sleep'ом?
Мда, типа ремикс басни Крылова "Мартышка и API"?! Чтобы ничего не тормозило, потоки должны работать максимально независимо, а не дергать постоянно общую изменяемую переменную (и тем более не бодаться постоянно за захват критсекций и т.п), т.к. после каждого изменения var1 на одном из ядер, она (вместе со всей 64-байтной линейкой) удаляется из кэшей первого уровня (L1) других ядер, и при последующем чтении грузится заново через общий кэш 2-го или 3-го уровня, что ес-но намного медленнее. А задавать в этом случае всякие приоритеты, бусты, свичи и слипы ва-аще не к селу, т.к. это лишь искуственно добавляет тормозов
Вы предлагаете не трогать приоритеты и вообще никак не изменять свойства потока, а только убрать общий доступ к переменной из потоков? А если у меня стоит задача проверки памяти? Получается я из этого потока читаю всю память, которая (возможно) исполняется и на основном потоке. А в основной поток впихнуть проверку памяти тоже не вариант, потому как при синхронном выполнении тормоза те же и еще и хуже.
Не предлагаю, а "требую" А также не заниматься бестолковым "цитированием" = полным дублированием постов, т.к. это той же оперы про мартышку Если он не нужен, то конечно убрать. Если же нужен, то подумать как уменьшить частоту обращения к этой переменной. Ты хоть на реальной задаче все это проверяешь или на пустых циклах без всяких action? И что из этого? Исполнение это то же чтение, а читать неизменяемую память могут сколько угодно потоков без всяких тормозов. Или у тебя модифицируемый код?
Код не модифицируемый, читаю только секции кода, но тормоза есть всеравно. Вы хотите сказать, что вот такой поток не будет выжирать процессорное время? void thread1() { while(1); }
Что значит "выжирать"? Он будет просто "бестолково" крутиться в цикле и греть процессор - если тебе именно это нужно, то ОК, значит "так и задумано". В противном случае - это глупость Ты бы лучше конкретную задачку пояснил, а не задавал бы обще-риторические вопросы. О каких "тормозах" ты говоришь? У тебя гуи-шная прога и при сканировании памяти перерисовка окон висит\тормозит? Или наоборт слишком часто пытаешься какие-то данные отображать (типа прогресса) и в итоге время сканирования увеличивается в разы?
Игра, однопоточная. окно D3D, при запуске параллельного потока, читающего всю память (конкретно - секции кода основного модуля и некоторых системных по типа kernel32/user32) снижается FPS. А задача в том, чтобы на fps не влияло, каким угодно образом.
Ну а общая переменная то зачем нужна? Раз FPS важнее, то и пусть себе второй поток "по тихому" память сканирует, пока не закончит или не найдет чего "подозрительного". Хотя если при этом будет притормаживать общий доступ к ОЗУ, то может и придется искусственно снизить скорость сканирования, если это допустимо
Вот как раз я и говорил об искусственном снижении скорости сканирования. Если вставить слипы, то как лучше это сделать, после сканирования 1 блока или чаще, и вообще, помогут ли слипы? ну и что делать если мой поток засаспендят?
Ага, а другие должны были догадаться, что скрывается за твоими action и нафиг тебе сдалась var1?! Не знаю. Тут по идее нужно как-то привязываться к работе основного потока, чтобы создать ему "все условия". Может попробовать это все не на разных потоках, а на файберах одного потока замутить, тогда и никому не придет в голову ничего суспендить
Спасибо, буду читать про файберы, главное что я узнал - вв принципе, что приоритеты потоков мне не помогут.
В твоем случае, с приотритетами имеет смысл поэкспериментировать, если привязать жестко оба потока к одному ядру, тогда второй поток будет работать только во время простоя основного. Если же позволять им работать на разных ядрах, то если в системе нет других активно работающих потоков, то твой idle-поток все равно будет крутиться как обычный normal на свободном ядре
2leo: перечитал соответствующие главы у рихтера, и пришел к такому же выводу. Но, на данный момент меня уже полностью устраивает решение на файберах, по скорости и по остальным параметрам. Чуть позже еще попробую реализовать тоже самое в отдельном потоке, с помощью CreateEvent+PulseEvent.