Я написал некоторый код потока с тем, что кажется неправильным предположением, что целые числа были потокобезопасными. Теперь кажется, что, хотя они и есть, мое использование их НЕ является потокобезопасным. Я использую глобальное целое число ThreadCount для хранения количества потоков. Во время создания потока я увеличиваю ThreadCount. Во время уничтожения потока я уменьшаю его. После того, как все потоки создаются, я жду их выполнения (ThreadCount должен упасть до 0), а затем написать мой окончательный отчет и выйти.Нитки завершены, но цикл не заканчивается
Иногда (5%), хотя я никогда не получаю 0, хотя посмертное обследование моего журнала показывает, что все потоки выполнялись и заканчивались. Таким образом, все признаки указывают на тотализацию ThreadCount. Я говорил себе, что это невозможно, поскольку это целое число, и я просто использую inc/dec.
Вот какой-то соответствующий код:
var // global
ThreadCount : integer; // Number of active threads
...
constructor TTiesUpsertThread.Create(const CmdStr : string);
begin
inherited create(false);
Self.FreeOnTerminate := true;
...
Inc(ThreadCount); // Number of threads created. Used for throttling.
end;
destructor TTiesUpsertThread.Destroy;
begin
inherited destroy;
Dec(ThreadCount); // When it reaches 0, the overall job is done.
end;
...
//down at the end of the main routine:
while (ThreadCount > 0) do // Sometimes this doesn't ever end.
begin
SpinWheels('.'); // sleeps for 1000ms and writes dots... to console
end;
Я думаю, что моя проблема с INC/DEC. Я думаю, что я получаю столкновений, когда два или более dec() попадают одновременно и оба читают одно и то же значение, поэтому они заменяют его одинаковым значением. ex: ThreadCount = 5, а два потока завершаются одновременно, оба считываются 5, заменяются на 4. Но новое значение должно быть равно 3.
Это никогда не сталкивается с трудностями в нашей тестовой среде (другое оборудование, топология , загрузка и т. д.), поэтому я ищу подтверждение, что это, вероятно, проблема, прежде чем я попытаюсь «продать» это решение для бизнес-единицы.
Если это моя проблема, я использую критический выбор для защиты inc/dec?
Спасибо, что посмотрели.
Увы, у меня нет абсолютно никаких фактов, чтобы поддержать его, я считаю, что 'Inc' и' Dec' не являются атомарными, особенно, особенно если у вас есть проверка диапазона. Возможно, вам стоит взглянуть на функцию WinAPI 'InterlockedIncrement (..) 'или использовать' TCriticalSection' или (возможно, быстрее) 'TMultiReadExclusiveWriteSynchronizer' –
Чтобы заблокировать все ваши потоки, вы можете использовать' WaitForMultipleObjects'. Тогда вам не нужен счетчик. Он возвращается, когда все объекты сигнализируются (или время истекает). –
Вы изучали OmniThreadLibrary? Возможно, ThreadCount может быть просто свойством контроллера, скорее, как подверженная ошибкам переменная, подсчитанная вручную –