Capítulo 7: Sincronização de Processos
� Fundamentos� O Problema da Seção Crítica� Sincronismo por Hardware� Semáforos� Problemas Clássicos de Sincronização� Regiões Criticas
Operating System Concepts
� Regiões Criticas� Monitores� Sincronização em Solaris 2 & Windows 2000
Fundamentos
� O acesso concorrente à dados compartilhados pode resultar em inconsistência dos dados.
� A manutenção da consistência dos dados requer mecanismos que assegurem a execução ordenada dos processos cooperantes.
� A Solução de Memória Compartilhada para o problema buffer-limitado (Capítulo 4) permite no máximo
Operating System Concepts
buffer-limitado (Capítulo 4) permite no máximo “tamanho_do_buffer – 1” items no buffer ao mesmo tempo. Uma solução, onde todos os items do buffer são usados requer alterações no algoritmo.� Suponha que queiramos modificar o algoritmo do produtor-
consumidor adicionando uma variável inteira counter, inicializada com 0 e incrementada cada vez que um novo item é adicionado ao buffer.
Buffer-Limitado
� Dados compartilhados
#define BUFFER_SIZE 10typedef struct {
. . .} item ;item buffer[BUFFER_SIZE];
Operating System Concepts
item buffer[BUFFER_SIZE];int in = 0;int out = 0;int counter = 0;
Buffer-Limitado
� Processo Produtor
while (1) {/* produz um item em nextProduced; */while (counter == BUFFER_SIZE)
Operating System Concepts
while (counter == BUFFER_SIZE); /* não faz coisa alguma */
buffer[in] = nextProduced;in = (in + 1) % BUFFER_SIZE;counter++;
}
Buffer-Limitado
� Processo Consumidor
while (1) {while (counter == 0)
; /* não faz coisa alguma */nextConsumed = buffer[out];
Operating System Concepts
nextConsumed = buffer[out];out = (out + 1) % BUFFER_SIZE;counter--;/* consome o item em nextConsumed */
}
Buffer-Limitado
� Os comandos
counter++;counter--;
devem ser executados atomicamente.
Operating System Concepts
� Operação atômica � operação que é totalmente realizada sem interrupção.
Buffer-Limitado
� O comando “counter++ ” pode ser implementado em linguagem de máquina da seguinte forma:
register1 = counterregister1 = register1 + 1counter = register1
Operating System Concepts
� O comando “counter-- ” pode ser implementado assim:
register2 = counterregister2 = register2 – 1counter = register2
Buffer-Limitado
� Se ambos o produtor e o consumidor tentarem atualizar o buffer concorrentemente, os comandos em linguagem assembly podem ser intercalados.
� A intercalação depende de como os processos produtor e consumidor são atendidos pela CPU (scheduled).
Operating System Concepts
Buffer-Limitado
� Considerando que counter é inicialmente 5. Podemos ter a seguinte intercalação de comandos:
T0 produtor: registrador1 = counter (registrador1 = 5)T1 produtor: registrador1 = registrador1 + 1 (registrador1 = 6)T2 consumidor: registrador2 = counter (registrador2 = 5)T3 consumidor: registrador2 = registrador2 – 1 (registrador2 = 4)
Operating System Concepts
T3 consumidor: registrador2 = registrador2 – 1 (registrador2 = 4)T4 produtor: counter = registrador1 (counter = 6)T5 consumidor: counter = registrador2 (counter = 4)
� O valor de counter poderia ser 4 ou 6, onde o resultado correto seria 5.
Condição de Corrida
� Condição de Corrida : Situação onde vários processos acessam e manipulam dados compartilhados concorrentemente. O valor final do dado compartilhado depende de qual processo termina por último.
� Para previnir condições de corrida, processos concorrentes devem ser sincronizados .
Operating System Concepts
devem ser sincronizados .
O Problema da Seção Crítica
� “n” processos todos competindo pelo uso de algum dado compatilhado.
� Cada processo tem um segmento de código, chamado seção crítica, no qual os dados compartilhados são acessados.
� Problema – assegurar que quando um processo está executando em sua seção crítica, a nenhum outro
Operating System Concepts
executando em sua seção crítica, a nenhum outro processo deve ser permitido executar na sua seção crítica.
Solução para o Problema da Seção Crítica
1. Exclusão Mútua . Se o processo Pi está executando em sua seção crítica, então nenhum outro processo pode estar executando na seção crítica dele.
2. Progresso . Se nenhum processo está executando em sua seção crítica e se algum processo quiser entrar em sua seção crítica, somente aqueles processos que precisem alterar a variável compartilhada poderão participar da decisão sobre qual processo será o próximo a entrar em sua seção crítica e esta seleção não
Operating System Concepts
será o próximo a entrar em sua seção crítica e esta seleção não poderá ser adiada indefinidamente.
3. Espera Limitada . Existe um limite para o número de vezes em que outros processos podem obter permissão para entrar em suas seções críticas, depois que um processo tenha feito uma solicitação para entrar em sua seção crítica e antes que a solicitação seja atendida. � Admitimos que cada processo esteja executando a uma velocidade
diferente de zero. Entretanto, não podemos fazer qualquersuposição em relação à velocidade relativa dos “n” processos.
Tentativas Iniciais para Resolver o Problema
� Somente 2 processos, P0 and P1
� Estrutura geral do processo Pi (outro processo Pj)do {
seção de entradaseção crítica
seção de saída
Operating System Concepts
seção de saídaseção remanescente
} while (1) ;� Os Processos podem compartilhar algumas variáveis
comuns para sincronizar as ações deles.
Algoritmo 1
� Variáveis compartilhadas : � int turn ;
inicialmente turn = 0� turn = i ⇒ Pi pode entrar na sua seção crítica
� Processo Pi
do {while (turn != i) ;
Operating System Concepts
while (turn != i) ;seção critica
turn = j ;seção remanescente
} while (1) ;� Satisfaz exclusão mútua , mas não progresso
Por quê?
Algoritmo 2
� Variáveis Compartilhadas� boolean flag[ 2 ] ;
inicialmente flag [0] = flag [ 1 ] = false.� flag [ i ] = true ⇒ Pi pronto para entrar na seção crítica
� Processo Pi
do {flag[ i ] := true;while (flag[ j ]) ;seção critica
Operating System Concepts
seção criticaflag [ i ] = false;
seção remanescente} while (1);
� Satisfaz exclusão mútua , mas não o requerimento de progresso e ainda pode deixar os 2 (dois) processos em deadlock, se ocorrer:T0 : P0 posiciona flag [0] = trueT1 : P1 posiciona flag [1] = true
Algoritmo 3
� Combinação das variáveis compartilhadas dos algoritmos 1 e 2.� Processo Pi
do {flag [ i ]:= true;turn = j;while (flag [ j ] && turn == j) ;
seção critica
Operating System Concepts
seção criticaflag [ i ] = false;
seção remanescente} while (1);
� Reune todos os três requerimentos; resolve o problema da seção crítica para dois processos.
Algoritmo da Padaria
� Antes de entrar na seção crítica, o processo recebe um número. O detentor do menor número entra na seção crítica.
� Se os processos Pi e Pj recebem o mesmo numero, se i < j, então P é servido primeiro; senão P é servido primeiro.
Seção Critica para n processos
Operating System Concepts
então Pi é servido primeiro; senão Pj é servido primeiro.� O esquema de numeração sempre gera números
incrementando a ordem de numeração; isto é, 1,2,3,4,5...
Algoritmo da Padaria
� Notação <≡ ordem lexicográfica (ticket #, process id #)� (a,b) < (c,d) se “a < c” ou se “a = c” e “b < d”� max (a0,…, an-1) é um número, k, tal que k ≥ ai para i = 0, …, n – 1
� Dados compartilhadosboolean choosing[ n ];int number[ n ];
Operating System Concepts
As estruturas de dados são inicializadas para false e 0 respectivamente.
Algoritmo da Padaria
do { choosing[ i ] = true;number[ i ] = max(number[ 0 ], number[ 1 ], …, numbe r [ n – 1 ]) + 1;choosing[ i ] = false;for (j = 0; j < n; j++) {
while (choosing[ j ]) ; while ((number[ j ] != 0) && ((number[ j], j ) < (number[ i], i ))) ;
Operating System Concepts
while ((number[ j ] != 0) && ((number[ j], j ) < (number[ i], i ))) ;}
seção criticanumber[ i ] = 0;
seção remanescente} while (1);
Sincronismo por Hardware
• Desabilitar ou mascarar interrupções;
• Instrução TestAndSet ( read-modify-write - RMW );
Operating System Concepts
• Instrução Swap
Sincronismo por Hardware
� Desabilitar ou mascarar interrupções:
Em um Sistema com Processador único poderia funcionar, entretanto nem sempre isso é possível.
Operating System Concepts
Sincronismo por Hardware
� Instrução TestAndSet ( read-modify-write - RMW ):
Testa e modifica o conteúdo de uma palavra atomicamente.
boolean TestAndSet(boolean &target) {boolean rv = target;target = true;
Operating System Concepts
target = true;return rv;
}
Exclusão Mútua com Test-and-Set� Dado compartilhado:
boolean lock = false;
� Processo Pi
do {while (TestAndSet(lock)) ;
seção críticalock = false;
Operating System Concepts
lock = false;seção remanescente
} while (1);
boolean TestAndSet (boolean &target) {
� Troca as duas variáveis atomicamente.void Swap(boolean &a, boolean &b) {
boolean temp = a;a = b;b = temp;
}� Processo Pi
do {
Exclusão Mútua com Swap
Operating System Concepts
do {key = true;while (key == true)
Swap(lock,key);seção crítica
lock = false;seção remanescente
} while (1);
Exclusão mútua com Espera Limitada TestAndSet� Dados compartilhados (inicializados com false ):
boolean lock;boolean waiting[n];
� Processo Pi
do {waiting [ i ] = true;key = true;while (waiting [ i ] && key)
key = TestAndSet (lock);waiting [ i ] = false;
Operating System Concepts
waiting [ i ] = false; seção crítica
j = ( i + 1 ) % n;while ( ( j != i ) && !waiting [ j ] )
j = ( j + 1 ) % n;if ( j == i )
lock = false;else
waiting [ j ] = false;seção remanescente
} while (1);
Semáforos
� Semaphore S – variável inteira� Só pode ser acessada via duas operações indivisíveis (atômicas)
wait (S) { signal (S) { while ( S≤≤≤≤ 0) S++;
; // no-op; } S--;
}
Operating System Concepts
}
� espera em ação � spinlock (não requer mudança de contexto)
Dijkstra:Originalmente: “wait =P ” (do holandês “proberen”, testar);
“signal=V ” (do holandês “verhogen”, incrementar).
Seção Crítica para n Processos
� Dado compartilhado:semaphore mutex; // inicialmente mutex = 1
� Processo Pi:
do {wait(mutex);
seção crítica
Operating System Concepts
seção críticasignal(mutex);
seção remanescente} while (1);
Semáforo como uma Ferramenta Geral de Sincronização
� Executa B em Pj somente após executar A em Pi
� Usa o semáforo synch inicializado para 0� Código:
Pi Pj
M M
A wait(synch)
Operating System Concepts
A wait(synch)signal(synch) B
Implementação de Semáforo
� Ferramenta de sincronização que não requer espera em ação� Define um semáforo como um registro
typedef struct {int value;struct process *L;
} semaphore;
Operating System Concepts
� Assume duas operações simples:� block suspende o processo que o invoca.� wakeup( P) retoma a execução do processo P bloqueado.
Implementação
� As operações sobre Semáforos agora são definidas como:
void wait (semaphore S) {S.value--;if (S.value < 0) {
add this process to S.L;block( );
}}
Operating System Concepts
}}
void signal (semaphore S) {S.value++;if (S.value <= 0) {
remove a process P from S.L;wakeup(P);
}}
Deadlock e Starvation (Inanição)
� Deadlock – dois ou mais processos estão esperando indefinidamente por um evento que só pode ser causado por um dos processos que estão em espera também.
� Suponha que S e Q são dois semáforos inicializados com 1P0 P1
wait(S); wait(Q);wait(Q); wait(S);
Operating System Concepts
wait(Q); wait(S);M M
signal(S); signal(Q);signal(Q) signal(S);
� Starvation – bloqueio indefinido. Um processo pode ficar indefinidamente em uma fila de semáforo na qual ele está suspenso.
Dois Tipos de Semáforos
� Semáforo de Contagem – valor inteiro que pode variar sobre um domínio irrestrito.
� Semáforo Binário – valor inteiro que pode variar somente entre 0 e 1; pode ser facilmente implementado.
� Um Semáforo de Contagem S pode ser implementado em função de semaforos binários.
Operating System Concepts
em função de semaforos binários.
Implementando S (semáforo de contagem)com Semáforos Binários
� Estruturas de dados:binary-semaphore S1, S2;int C:
� Inicialização:S1 = 1S2 = 0
Operating System Concepts
C = valor inicial do semaforo S
� operação waitwait(S1);C--;if (C < 0) {
signal(S1);wait(S2);
}signal(S1);
void wait (semaphore S) {S.value--;if (S.value < 0) {
add this process toS.L;block( );
}}
Implementando S (semáforo de contagem)com Semáforos Binários
Operating System Concepts
� operação signalwait(S1);C ++;if (C <= 0)
signal(S2);else
signal(S1);
void signal (semaphore S) {S.value++;if (S.value <= 0) {
remove a processP from S.L;wakeup(P);
}}
Valores Iniciais: S1 = 1;S2 = 0;C = valor inicial do semáforoS;
Problemas Clássicos de Sincronização
� O Problema do Buffer-Limitado
� O Problema dos Leitores-Gravadores
� O Problema dos Filósofos Comensais
Operating System Concepts
O Problema do Buffer-Limitado
� Dados compartilhados
semaphore full, empty, mutex;
Inicialmente:
full = 0, empty = n, mutex = 1
Operating System Concepts
full = 0, empty = n, mutex = 1
O Problema do Buffer-LimitadoProcesso Produtor
do { …
produz um item em nextp…
wait(empty);wait(mutex);
…
Operating System Concepts
…soma nextp ao buffer
…signal(mutex);signal(full);
} while (1);
O Problema do Buffer-LimitadoProcesso Consumidor
do { wait(full)wait(mutex);
…remove um item do buffer para nextc
…signal(mutex);
Operating System Concepts
signal(mutex);signal(empty);
…consome o item em nextc
…} while (1);
� 1º Problema dos Leitores-Gravadores:Nenhum Leitor espera, a menos que Gravador já esteja na seção crítica;
� 2º Problema dos Leitores-Gravadores:Gravador esperando para ter acesso bloqueia todos os novos leitores.
O Problema dos Leitores-Gravadores
novos leitores.
Operating System Concepts
O Problema dos Leitores-Gravadores (1º Problema)
� Dados Compartilhados:
semaphore mutex, wrt;
Inicialmente:
mutex = 1, wrt = 1, readcount = 0
Operating System Concepts
mutex = 1, wrt = 1, readcount = 0
O Problema dos Leitores -GravadoresProcesso Gravador
wait(wrt);…
gravação é realizada…
signal(wrt);
Operating System Concepts
O Problema dos Leitores -GravadoresProcesso Leitor
wait(mutex);readcount++;if (readcount == 1)
wait(wrt);signal(mutex);
…
Operating System Concepts
…leitura é realizada
…wait(mutex);readcount--;if (readcount == 0)
signal(wrt);signal(mutex):
O Problema dos Filósofos Comensais
Operating System Concepts
� Dados Compartilhados: semaphore chopstick[5];
Inicialmente todos os valores são 1
O Problema dos Filósofos Comensais
� Filósofo i:do {
wait(chopstick[ i ])wait(chopstick[(i+1) % 5])
…come…
signal(chopstick[ i] );
Operating System Concepts
signal(chopstick[ i] );signal(chopstick[(i+1) % 5]);
…pensa…
} while (1);
Evitando Deadlocks e Inanição
� Permitir que no máximo quatro filósofos estejam sentados simultaneamente à mesa;
� Permitir que um filósofo pegue seus pauzinhos somente se ambos estiverem disponíveis (para fazer isso ele deve pegá-los em uma seção crítica);
Operating System Concepts
� Usar uma solução assimétrica, isto é, um filósofo ímpar pega primeiro o pauzinho à sua esquerda e depois o pauzinho à sua direita, enquanto um filósofo par pega o pauzinho à sua direita e depois o que está a sua esquerda.
Estruturas de Sincronização de Alto Nível
� Região Crítica ouRegião Crítica Condicional;
Operating System Concepts
� Monitor.
Regiões CríticasErros de Programação:� signal (mutex);
. . .seção crítica. . .
wait (mutex);
� wait (mutex);
--> inversão da ordem das operações:violação do requisito de exclusão mútua;
--> substituição de signal por wait:
Operating System Concepts
� wait (mutex);. . .seção crítica. . .
wait (mutex);
� esquecimento do wait ou do signal
--> substituição de signal por wait:ocorrência de deadlock;
--> omissão do wait ou signal:violação da exclusão mútua e deadlock.
Regiões Críticas
� Construção de sincronização de alto-nível� Uma variável compartilhada v do tipo T, é declarada como:
v: shared T� A variável v é accessada somente dentro do comando:
region v [ when B ] do S
onde B é uma expressão booleana.
Operating System Concepts
� Enquanto o comando S está sendo executado, nenhum outro processo pode acessar a variável v.
� A parte [ when B ] é opcional e quando usada transforma uma região crítica em uma região crítica condicional.
Regiões Críticas
� As regiões relativas a mesma variável compartilhada só permitem a entrada de um processo por vez.
� Assim, se dois comandos:region v when (true) S1;region v when (true) S2;
forem executados concorrentemente, em processos sequenciais distintos, o resultado será equivalente à execução sequencial de:
Operating System Concepts
distintos, o resultado será equivalente à execução sequencial de:“S1 seguido de S2”; ou“S2 seguido de S1”.
� Quando um processo tenta entrar na região crítica, a expressão Bé avaliada. Se B for true, o comando S será executado. Se for false, o processo abandonará a exclusão mútua e entrará em espera até que B se torne true e que nenhum outro processo esteja na região associada com v.
Exemplo – Buffer-Limitado
� Dados compartilhados:
struct buffer {int pool[ n ];int count, in, out;
}
Operating System Concepts
}
Buffer-Limitado Processo Produtor
� O Processo Produtor insere nextp dentro do buffer compartilhado
region buffer when ( count < n) {pool [ in ] = nextp;in:= (in+1) % n;count++;
}
Operating System Concepts
}
Buffer-Limitado Processo Consumidor
� O Processo Consumidor remove um item do buffer compartilhado e coloca-o em nextc
region buffer when (count > 0) {nextc = pool[out];out = (out+1) % n;count --;
Operating System Concepts
count --;}
Implementação da construção da região condicional
� As seguintes variáveis estão associadas com a variável compartilhada x:
semaphore mutex, first-delay, second-delay;int first-count, second-count;
� O acesso mutuamente exclusivo à seção crítica é fornecido por mutex .
Operating System Concepts
fornecido por mutex .
� Se um processo não puder entrar na seção crítica porque a expressão boleana B é false, ele inicialmente irá esperar no semáforo first_delay ; movido para o semáforo second-delay antes de receber autorização para reavaliar B.
wait (mutex);while (!B) {
first_count++;if (second_count > 0)
signal (second_delay);else
signal (mutex);wait (first_delay);first_count--;second_count++;if (first_count > 0)
signal (first_delay);
Implementação da construção da região condicional
Operating System Concepts
signal (first_delay);else
signal(second_delay);wait (second_delay);second_count--;
}S; // comando protegidoif (first_count) > 0)
signal (first_delay);else if (second_count > 0)
signal (second_delay);else
signal(mutex);
� Observar o número de processos que estão esperando em first-delay e second-delay , com first-count e second-count respectivamente.
� O algoritmo assume a ordem FIFO no enfileiramento dos processos para o semáforo.
Implementação da construção da região condicional
Operating System Concepts
� Para uma disciplina de enfileiramento arbitrária, uma implementação mais complicada é requerida.
Monitores
� Construção de sincronização de Alto-Nível que permite o compartilhamento seguro de um tipo abstrato de dado entre os processos concorrentes.
monitor monitor-name{
declarações de variáveis compartilhadasprocedure body P1 (…) {
. . .}procedure body P2 (…) {
Operating System Concepts
procedure body P2 (…) {. . .
} procedure body Pn (…) {
. . .} {
código de inicialização}
}
Visão Esquemática de um Monitor
Operating System Concepts
Monitores
� Para permitir que um processo espere em um monitor, uma variável do tipo condition deve ser declarada, como:
condition x, y;� As variáveis do tipo condition só podem ser usadas
com as operações wait e signal .� A operação
Operating System Concepts
� A operaçãox.wait();
significa que o processo que invoca esta operação é suspenso até que um outro processo invoque
x.signal();� A operação x.signal reinicia exatamente no ponto em
que o processo foi suspenso. Se nenhum processo está suspenso, então a operação signal não tem efeito.
Monitor com Variáveis Condition
Operating System Concepts
Continuidade após x.signal ( )
“x.signal ( )” invocada pelo processo “P”, e “Q” está suspenso associado à condição “x”:
Duas possibilidades:
Operating System Concepts
1. “P” espera até “Q” liberar o monitor ou espera por uma outra condição;
2. “Q” espera até “P” liberar o monitor ou espera por uma outra condição.
Exemplo dos Filósofos Comensais
monitor dp {
enum { thinking, hungry, eating } state[5];condition self [ 5 ];void pickup (int i) // following slidesvoid putdown (int i) // following slidesvoid test (int i) // following slidesvoid init ( ) {
Operating System Concepts
void init ( ) {for ( int i = 0; i < 5; i++)
state [ i ] = thinking;}
}
Filósofos Comensaisvoid pickup (int i) {
state [ i ] = hungry;test [ i ];if (state [ i ] != eating)
self [ i ].wait();}void putdown (int i) {
state[ i ] = thinking;// test left and right neighborstest ( ( i+4 ) % 5);
Operating System Concepts
test ( ( i+4 ) % 5);test ( ( i+1 ) % 5);
}void test (int i) {
if ( (state [ (i + 4) % 5] != eating) &&(state [ i ] == hungry) &&(state [ (i + 1) % 5] != eating ) ) {
state [ i ] = eating;self [ i ].signal( );
}}
Filósofos Comensais
Quando o filósofo estiver faminto invoca “pickup” e, após ter conseguido comer, invoca “putdown” e começa a pensar:
dp.pickup (i);. . .
Operating System Concepts
. . .come. . .
dp.putdown (i);
Implementação de Monitor usando Semáforos
� Variáveis semaphore mutex; // (initially = 1)semaphore next; // (initially = 0)int next-count = 0;
� Cada procedure externa F será substituída porwait(mutex);
…body of F;
Operating System Concepts
body of F;…
if (next-count > 0)signal(next)
else signal(mutex);
� A Exclusão Mútua com um monitor é assegurada.
Implementação de Monitor
� Para cada variável condition x, nós teremos:semaphore x-sem; // (initially = 0)int x-count = 0;
� A operação x.wait pode ser implementada como:
x-count++;if (next -count > 0)
Operating System Concepts
if (next -count > 0)signal(next);
elsesignal(mutex);
wait(x-sem);x-count--;
Implementação de Monitor
� A operação x.signal pode ser implementada como:
if (x-count > 0) {next-count++;signal(x-sem);wait(next);
Operating System Concepts
next-count--;}
Implementação de Monitor
� Construção Condicional wait: x.wait(c);� c – expressão inteira avaliada quando a operação wait é
executada.� valor de c (um número de prioridade) armazenado com o
nome do processo que está suspenso.� quando x.signal é executada, o processo com menor número
de prioridade associado é o próximo a ser reiniciado.� Verificação de duas condições para estabelecer a exatidão
do sistema:
Operating System Concepts
do sistema:� Os processos do usuário devem sempre fazer suas
chamadas ao monitor em uma sequência correta.� Deve ser assegurado que um processo não-cooperativo não
ignore a porta de exclusão mútua fornecida pelo monitor, e tente acessar recursos compartilhados diretamente, sem usar o protocolo de acesso.
Monitor para Alocação de um recurso
monitor ResourceAllocation{
boolean busy;condition x;
void acquire (int time) {if (busy)
x.wait (time);busy = true;
}
Operating System Concepts
}
void release () {busy = false;x.signal ();
}
void init () {busy = false;
}}
Acesso ao recurso
r.acquire ( t );. . .acessa o recurso. . .
r.release ( );
Operating System Concepts
r.release ( );
Sincronização Solaris 2
� Implementa uma variedade de travas para suportar multi-tarefa, multithreading (incluindo threads real-time), e multi-processamento.
� Usa mutexes adaptáveis para obter eficiência quando estiver protegendo dados de pequenos segmentos de código.
Operating System Concepts
� Usa variáveis condition e travas leitores-gravadoresquando longas seções de código precisam acessar aos dados.
� Usa turnstiles (porta giratória) para ordenar a lista de threads que estão esperando em um mutex adaptável ou em uma trava leitor-gravador.
Sincronização Windows 2000
� Usa máscaras de interrupção para proteger o acesso a recursos globais em um sistema uniprocessador.
� Usa spinlocks em sistemas multiprocessadores.
� Fora do Kernel: fornece dispatcher objects (objetos despachantes) que podem funcionar de acordo com
Operating System Concepts
despachantes) que podem funcionar de acordo com mutexes e semáforos.
� Dispatcher objects também podem prover events. Um event age tal como uma variável condition.
� Um dispatcher object pode estar no estado signal ou não-signal.