Procedure StopThreads;
var
h,CurrTh,ThrHandle,CurrPr:thandle;
Thread:TThreadEntry32;
begin
CurrTh:=GetCurrentThreadId;
CurrPr:=GetCurrentProcessId;
h:=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
if hINVALID_HANDLE_VALUE then
begin
Thread.dwSize:=SizeOf(TThreadEntry32);
if Thread32First(h,Thread) then
repeat
if (Thread.th32ThreadIDCurrTh)and(Thread.th32OwnerProcessID=CurrPr) then
begin
ThrHandle:=OpenThread(THREAD_SUSPEND_RESUME,false,Thread.th32ThreadID);
if ThrHandle>0 then
begin
SuspendThread(ThrHandle);
CloseHandle(ThrHandle);
end;
end;
until not Thread32Next(h,Thread);
CloseHandle(h);
end;
end;
Procedure RunThreads;
var
h,CurrTh,ThrHandle,CurrPr:thandle;
Thread:TThreadEntry32;
begin
CurrTh:=GetCurrentThreadId;
CurrPr:=GetCurrentProcessId;
h:=CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);
if hINVALID_HANDLE_VALUE then
begin
Thread.dwSize:=SizeOf(TThreadEntry32);
if Thread32First(h,Thread) then
repeat
if (Thread.th32ThreadIDCurrTh)and(Thread.th32OwnerProcessID=CurrPr) then
begin
ThrHandle:=OpenThread(THREAD_SUSPEND_RESUME,false,Thread.th32ThreadID);
if ThrHandle>0 then
begin
ResumeThread(ThrHandle);
CloseHandle(ThrHandle);
end;
end;
until not Thread32Next(h,Thread);
CloseHandle(h);
end;
end;
Проблема многопоточного доступа к переменной
Помогите пожалуйста решить следующую проблему:
У меня есть некий класс A который имеет некую переменную B. Я создаю N таких объектов в памяти, и потом из двух или более разных потоков (многозадачность) меняю вышеупомянутую переменную в каждом конкретном объекте по разному и в разное время. Проблема в том что мне НЕЛЬЗЯ чтобы к этой переменной в одном отдельно взятом созданном в памяти объекте мог получить доступ более чем один поток одновременно. В теории это можно решить при помощи создания отдельного объекта CRYTICAL_SECTION для каждого созданного экземпляра класса и защитой этой критической секцией метода присвоения переменной значения. Но объектов планируется до сотни тысяч в памяти. Как мне поступить в этом случае?
С уважением.
Скажем мне нужно запретить одновременный доступ к переменной класса, но для каждого созданного объекта отдельно. В смысле чтоб блокирование этой переменной не блокировало изменение этой же переменной в других экземплярах этого класса.
помоему, без стандартных объектов синхронизации никак. на выбор -- критические секции, мьютексы, семафоры, события
можно попробовать остоновить все потоки кроме текущего,внести изменения и запустить снова.
не думаю, что это оптимальный вариант. ведь пока один объект занят, другие потоки могут работать с остальными объектами. а там получается, что в любой момент времени работает только один поток. т.е. по факту никакой многопоточности и нет
Так они защитят участок памяти? Или условный участок кода? Вот что я понять не могу
В линухе можно использовать sig_atomic, но есть один недостаток - у нее значение типа int. В винде помоему тоже есть что-то связанное с atomic - гарантирующее отсутствие одновременного обращения из двух процессов/потоков (точнее даже - гарантия того что операция присваивания/чтения значения этой переменной займет не более одного такта).
А вообще в стандарте C++09 таки обещают этот тип "леголизовать" официальным термом - atomic. (Ура товарищи!!!)
То есть, если переменная типа int - ищите в сторону atomic, а если нет -используйте критическую секцию (незабудьте прочитать перед этим про состояние "гонок", дедлоки... ).
Цитата:
В теории это можно решить при помощи создания отдельного объекта CRYTICAL_SECTION для каждого созданного экземпляра класса
Добавляй прямо в метод.
Цитата:
не думаю, что это оптимальный вариант. ведь пока один объект занят, другие потоки могут работать с остальными объектами. а там получается, что в любой момент времени работает только один поток. т.е. по факту никакой многопоточности и нет
да, действительно немного не подумал.
А мьютексы, семафоры - ето средства межпроцесорного взаимодействия. И, помоему, использовать их в пределах одного процесса тоже не очень.
Можно попробывать тормозить только те потоки которые пытаються получить доступ к уже изменяемым данным.
Перед изменением выставляеш какой нить флаг. Далее если флаг выставлен приостанавливаеш текущий поток. После изменений снимаеш флаг и запускаеш приостановленные потоки.
Использование CS оптимальнее по производительности, чем использование других объектов синхронизации. Однако, нет ничего плохого в использовании мьютексов и семафоров внутри одного процесса. Это вполне нормально. Сам по себе термин "межпроцессорное взаимодействие" не совсем корректен, процессы не могут взаимодействовать, т.к. они всего-лишь агрегаторы ресурсов. Взаимодействуют же в любом случае потоки, т.к. они являются единственной "движущей силой".
Теперь к сути топика.
Для решения проблемы нужно блокировать конкретные объекты, но это накладно в силу их количества. Можно блокировать все объекты, но это сильно снижает производительность. Берем промежуточное решение: разбиваем объекты на логические блоки и блокируем блоками.
Но это все лечение симптомов, а не болезни. Проблема здесь значительно глубже.
lexluther, ты уверен, что тебе необходимо такое огромное количество объектов? Ты уверен, что у всех потоков должен быть доступ ко всему простанству этих объектов? Ты уверен, что все потоки должны читать и писать в это пространство?
Я вот почти уверен в обратном: если пересмотреть архитектуру и принцип взаимодействия можно отказаться от всех вышеобозначенных сложностей.
У MS уже давно есть набор API для таких случаев (правда, судя по описанию, там есть кое-какие ограничения):
Цитата:
Останавливать потоки - это неправильный метод, опасный метод, ну и глупый метод!
А можна поподробнее. Хотябы буду знать в чем глуп.
Метод опасен потому, что опять же остановка и запуск потоков не происходят мгновенно и не атомарно. Кроме того между снятием снапшота и остановкой потоков из этого снепшота, можно насоздавать такое огромное множество новых потоков, что вся эта схема сходит на нет. Но самое вероятное, что пока один поток останавливает другие, его остановят самого и всё... приложение встало (deadlock). Кроме того, ка ты будешь отличать потоки остановленные твоим механизмом и остановленные по другим причинам?