while (!fim) {
seção_não_crítica;
lock();
seção_crítica;
unlock();
}
Uma solução para o problema tem que satisfazer:
lock()
{
while (vez != i);
};
unlock()
{
vez = j;
};
Problema:
lock()
{
quer_entrar[i] = 1;
while (quer_entrar[j]);
};
unlock()
{
quer_entrar[i] = 0;
};
lock()
{
quer_entrar[i] = 1;
vez = j;
while
(quer_entrar[j] && turn == j);
};
unlock()
{
quer_entrar[i] = 0;
};
lock()
{
escolhendo[i] = 1;
numero[i] = max(numero[0..n-1]) + 1;
escolhendo[i] = 0;
for (j = 0; j < n; j++) {
while (escolhendo[j]);
while ((numero[j] != 0) &&
(numero[j],j)<(numero[i],i));
};
}
unlock()
{
numero[i] = 0;
};
aonde (a,b) < (c,d) se (a < c) ou (a = c e b < d)
Trocas de contexto acontecem quando o escalonador é chamado: por eventos internos ou eventos externos:
Desvantagens:
lock()
{
disable_interrupts();
};
unlock()
{
enable_interrupts();
};
int M = 0;
lock(M)
{
disable_interrupts();
while (M) {
enable_interrupts();
disable_interrupts();
};
M = 1;
enable_interrupts();
};
unlock(M)
{
disable_interrupts();
M = 0;
enable_interrupts();
};
A maioria dos processadores modernos implementa alguma forma de read-modify-write:
int M = 0;
lock(M)
{
while (test&set(M) == 1);
};
unlock(M)
{
M = 0;
};
key: mutex; ... lock(M); secao_critica; unlock(M); ...
P0 P1 bed: B; ... ... if (!dado_pronto) dado_pronto = 1; sleep(B); wakeup(B); /* dado pronto */ ...
better_lock(M)
{
lock(M.guard);
if (!M.free) {
sleep(M.bed, M.guard);
M.free = 0;
} else {
unlock(M.guard);
};
}
better_unlock(M)
{
lock(M.guard);
M.free = 1;
wakeup(M.bed);
unlock(M.guard);
}
wait(S)
{
while (S <= 0);
S--;
};
signal(S)
{
S++;
};
int S = 1;
lock(S)
{
wait(S);
};
unlock(S)
{
signal(S);
};