- Код: Выделить всё
uses Windows;
var SEC1,SEC2 :TRTLCriticalSection;
эти переменные для программиста ассоциируются с ресурсами, которые необходимо блокировать. Блокировка возможна только для различных (конкурирующих) потоков одного процесса. Например: SEC1 может быть логически связан с таким ресурсом как
- Код: Выделить всё
LS:TList
Если вы не хотите чтобы другой поток читал список (TList) во время модификации, то следует в начале модификации и в начале чтения списка вызвать
- Код: Выделить всё
EnterCriticalSection(SEC1);
а в конце
- Код: Выделить всё
LeaveCriticalSection(SEC1);
Естественно, вызвав перед чтением списка Enter... другой поток при попытке модификации обязан вызвать (это ложится на плечи программиста) Enter... при этом он уснёт до тех пор, когда первый поток после чтения списка вызовет Leave... И наоборот
- Код: Выделить всё
// в начале программы
InitializeCriticalSection(SEC1); //Подготовка переменной SEC1
InitializeCriticalSection(SEC2);
EnterCriticalSection(SEC1); // Ресурс заблокирован
// С этого места поток может заснуть, если конкурирующий поток
// заблокировал ресурс раньше.
LeaveCriticalSection(SEC1); // Ресурс освобождён
// в конце программы
DeleteCriticalSection(SEC1); // Теперь можно завершать программу
DeleteCriticalSection(SEC2); // И нельзя использовать SEC1, SEC2
Случай мёртвой блокировки (dead lock) при которой несколько потоков виснут:
1. Поток1: Enter..(SEC1);
2. Поток2: Enter..(SEC2);
3. Поток1: Enter..(SEC2); 1-й засыпает т.к. 2-й уже вошёл в критическую секцию SEC2
4. Поток2: Enter..(SEC1); 2-й засыпает т.к. 1-й уже вошёл в критическую секцию SEC1 и оба никогда не проснутся.
Чтобы избежать такой ситуации следует пронумеровать кр.секции и входить поочереди в порядке возрастания номера, а выходить в обратном порядке.