Upload
others
View
32
Download
0
Embed Size (px)
Citation preview
1
Sistemas OperativosSistemas Operativos
66ªª parte parte -- SincronizaSincronizaçção de Processos ão de Processos
Prof. José Rogado
Prof. Pedro Gama
Universidade Lusófona
Adaptação LIG e Notas por Dr. Adriano Couto
2
6.2 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SincronizaSincronizaçção de Processosão de Processos� Objectivos:
� Noções de concorrência, seus problemas e a necessidade de sincronização
� Conhecer os principais mecanismos de sincronização (processos ou threads), seu funcionamento e implementação
� Entender os problemas clássicos da sincronização
� Noções de Concorrência
� Secções Críticas
� Soluções Software
� Hardware de Sincronização
� Semáforos
� Problemas Clássicos de Sincronização
� Monitores
� Exemplos de Sincronização
� Transacções Atómicas
3
6.3 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ConcorrênciaConcorrência
� Vantagens de utilizar execução concorrente
� Performance
� Economia
� Poucas das linguagens de programação mais divulgadas suportam programação concorrente (Java é uma excepção)
� Existem vários paradigmas de programação concorrente
� Cada modelo requer uma abordagem específica
� Não existem modelos comuns
� Os suportes da concorrência a nível dos sistemas operativos são geralmente de baixo nível
� Próximos do hardware
Já anteriormente se falou das vantagens da concorrência.
Desde 2005 que os abricantes de CPU (Intel e AMD) passarm a apostar na multi-
programação ( multi-processo – multi-thread) como única forma de contínuar a
aumentar o desempenho, uma vez que não é viável continuar a apostar no aumento
das velocidade de relógio.
Ver o site: hhtp://www.go-parallel.com da Intel.
Daremos agora enfâse às soluções para os problemas associados à concorrência.
O aluno deve entender que há vários paradigmas para resolver esses problemas, e
reconhecer os mecanismos básicos subjacentes. Esse mecanismos são geralmente
garantidos (ao nível mais baixo) pelo próprio hardware. Deverá entender porque
razão o hardware tem de fornecer este suporte!
4
6.4 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ProblemasProblemas
� Acessos simultâneos (concorrentes) a dados partilhados por vários fluxos de execução podem gerar inconsistências
� Processos cooperando num mesma aplicação usando memória partilhada
� Processos acedendo aos mesmos dispositivos de I/O
� Threads dentro de um mesmo processo utilizando as mesmas varáveis globais ou o mesmo I/O
� Para manter a consistência dos dados são necessários mecanismos para garantir a serialização de fluxos de execução concorrentes
Nota: em computação há duas acepções para a palavra serialização: em estruturas de
dados e programação OO é o processo de escrever e ler uma estrutura de dados/objecto
por um canal série (um byte de cada vez); em sistemas concorrentes descreve a
propriedade de as operações efectuadas concorrentemente terem o mesmo resultado
se executadas uma de cada vez. Quando isso não acontece temos um problema...
5
6.5 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Cruzamento de TrCruzamento de Trááfegofego
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Aqui há um problema se serialização: se os véiculos passam um de cada vez temos
um resultado diferente e melhor.
Os 2 veículos competem/concorrem por uma região comum: querem estar ao mesmo
tempo no mesmo espaço.
6
6.6 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
shared double balance;
Code for p1 Code for p2
. . . . . .
balance = balance + amount; balance = balance - amount;
. . . . . .
balance+=amount balance-=amount
balance
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
SecSecçção Crão Críítica: exemplotica: exemplo
2 processos manipulam a mesma varável ao mesmo tempo.
Esta é uma situação que está sempre a acontecer nas nossas contas bnacárias!
-- “ao mesmo tempo”? Mas se existir apenas um processador?
Não esquecer a prempção!
7
6.7 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
…
load R1, balance
load R2, amount
…
load R1, balance
load R2, amount
sub R1, R2
store R1, balance
…
add R1, R2
store R1, balance
…
Timer interrupt
Timer interrupt
Execution of p1 Execution of p2
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
SecSecçção Critica: problemaão Critica: problema
A partir do momento em que há prrempção a comutação de processos pode ocorrer
em qualquer momento!!!!
Como nenhum dos processos está a efectuar uma chamadade sistema, o Kernel não
sabe que estáo a fazer algo crítico!
8
6.8 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
� Secção Crítica (SC): Zona de código que só pode ser utilizada por um processo de cada vez, em exclusão mútua
� Existe uma competição entre processos para executar a secção crítica
� A secção crítica pode ter forma diferente (código) em cada processo
� ∴ Não é facilmente detectavel por análise estatística
� Sem exclusão mútua, o resultado da execução dos processos éindeterminado
� São necessários mecanismos do SO para resolver os problemas levantados pela concorrência
SecSecçção Crão Críítica: definitica: definiççãoão
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Criamos o conceito de Seccção Crítica.
9
6.9 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
do {entrada na secção crítica
secção crítica
saída da secção crítica
resto do processo
} while (TRUE) ;
Estrutura de uma SecEstrutura de uma Secçção Crão Crííticatica
Secção Crítica
Protocolo para usar uma secção crítica: o processo ou thread avisa que quer entrar
e avisa quando sai.
Cabe ao programador garantir este protocolo.
O programador só deve efectuar uma manipulação das variáveis (recursos em geral)
que são objecto de concorrência depois de entrar na secção critica usando o protocolo.
Se o fizer sem respeitar o protocolo irá arder para sempre no inferno de Belzebu, isto
é, a aplicação irá destruir dados de forma aleatória. (Se esse dados representarem
dinheiro haverá lágrimas, baba e ranho na cara dos utilizadores e o programador passará a gestor de hedge funds).
10
6.10 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SoluSoluçção do Problemaão do Problema
1. Exclusão Mútua – Se o processo Pi está a executar uma secção crítica, então nenhum outro processo pode estar a executar a mesma secção crítica (SC) em simultâneo
2. Progresso – Só os processos que competem para uma secção crítica são elegíveis para entrar nessa secção, e a partir do momento em que um processo requisita o acesso à SC este não pode ser adiado indefinidamente
3. Espera Limitada – Depois de um processo ter requisitado o acesso à SC, só um número limitado de outros processos podem entrar na SC antes deste
Definição de uma SC. Repare-se na afirmação:
”só processos que competem para uma secção crítica são elegíveis
para entrar nessa secção”.
Ou seja não pode entrar quem não mostrou interesse em entrar (1ª zona
colorida no slide anterior)
11
6.11 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Algumas SoluAlgumas Soluçções Possões Possííveisveis
� Desactivar as interrupções
� Só válido em mono-processadores
� Kernel não preemptivo
� Impacto no desempnho
� Podem perder-se eventos p/ outros processos.
� Utilizar soluções de Software (Peterson)
� Soluções complexas válidas para poucos processos
� Situações de bloqueio difíceis de evitar
� Utilizar soluções de Hardware
� Instruções específicas do processador
� Geralmente utilizadas no kernel
� Fornecidas às aplicações através de APIs de programação de mais alto nível
� Pthreads
� Java
Estas soluções são discutidas a seguir.
12
6.12 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Desactivar as InterrupDesactivar as Interrupççõesões
shared double balance;
Code for p1 Code for p2disableInterrupts(); disableInterrupts();
balance = balance + amount; balance = balance - amount;
enableInterrupts(); enableInterrupts();
� As interrupções podem ficar desactivadas durante tempos demasiados longos
� Ao sincronizar p1 e p2 está-se a impedir que outros processos possam continuar a sua execução
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
13
6.13 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
UtilizaUtilizaçção de uma Varião de uma Variáável de Sincronizavel de Sincronizaççãoão
shared boolean lock = FALSE;
shared double balance;
Code for p1 Code for p2/* Acquire the lock */ /* Acquire the lock */
while(lock) while(lock)
; ;
lock = TRUE; lock = TRUE;
/* Execute critical sect */ /* Execute critical sect */
balance = balance + amount; balance = balance - amount;
/* Release lock */ /* Release lock */
lock = FALSE; lock = FALSE;
p1
p2
Blo
cked
at while
lock = TRUE
lock = FALSE
Inte
rrup
t
Inte
rrup
t
Inte
rrup
t
Espera activa !!
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Se a interrupção (preempção) ocorrer num momento “favorável”, como represesentado,
a solução funciona. Isto, se p1 mudar a variável antes da interrupção, p2 irá ficar
bloqueado no while, em espera activa, isto é em execução contínua, usando o CPU.
O problema ocorre quando a interrupção ocorre depois do teste e antes da afectação
da variável!!! Lembro-nos que estão em causa várias instruções máquina, apesar
de ser um curto intervalo de tempo!!!
14
6.14 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Falsa Falsa ““SoluSoluççãoão”” !!!!
shared boolean lock = FALSE;
shared double balance;
Code for p1 Code for p2/* Acquire the lock */ /* Acquire the lock */
while(lock) ; while(lock) ;
lock = TRUE; lock = TRUE;
/* Execute critical sect */ /* Execute critical sect */
balance = balance + amount; balance = balance - amount;
/* Release lock */ /* Release lock */
lock = FALSE; lock = FALSE;
� O processo p1 … testa a variável, e encontra-a com o valor FALSE
� Decide entrar na secção crítica, sai do while e é interrompido
� O processo p2 … testa a variável e encontra-a também a FALSE
� Decide entrar também na secção crítica
� Resultado: dois processos na mesma secção crítica…
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Depois de efectuado o teste no while o processo CORRE para mudar o valor do lock.
Nesta corrida o outro processo pode ganhar, mudando os resultados.
Trata-se de uma corrida crítica (em inglês race condition). Os resultados são
aleatórios e esta solução não tem a propriedade de serialização.
15
6.15 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ProtecProtecçção doão do LockLock
enter(lock) { exit(lock) {
disableInterrupts(); disableInterrupts();
/* Loop until lock is TRUE */ lock = FALSE;
while(lock) { enableInterrupts();
/* Let interrupts occur */ }
enableInterrupts();
disableInterrupts();
}
lock = TRUE;
enableInterrupts();
}
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
� Utilizam-se dois system calls (enter e exit) que permitem manipular a variável lock de forma segura, desactivando as interrupções antes de mudar o seu valor
� Permite limitar o tempo em que as interrupções estão desactivadas
� Não adaptado para sistemas multiprocessador
Aqui estamos a avisar o kernel (atrvés de uma SysCall) que vamos manipular
uma variável especial.
Mas se não há apio específico do hardware o kernel também vai ter que
desactivar interrupções (para o processador onde a chamada foi efectuada).
16
6.16 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Hardware Hardware de Sincronizade Sincronizaççãoão
� A maioria dos processadores modernos fornecem instruções específicas para implementar secções críticas
� Atómicas = não interruptíveis
� Dois tipos mais frequentes
� Test-and-set
� Teste de uma variável em memória e modificação do seu valor
� Swap
� Troca (swap) os valores de duas variáveis em memória
A arquitectura de processador x86 possuia a instrução LOCK que garante que
a(s) instruções seguintes são atómicas.
17
6.17 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
InstruInstruççãoão TestTest--andand--SetSet
� Definição:
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
Este é a definição equivalente, em C, do TestAndSet.
O hardware garante a atomicidade.
18
6.18 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Detalhe doDetalhe do Test and SetTest and Set
FALSEm
PrimaryMemory
…R3 …
DataRegister
CCRegister
(a) Antes de executar TS
TRUEm
PrimaryMemory
FALSER3 =0
DataRegister
CCRegister
(b) Depois de executar TS
� TS(m): [Reg_i = memory[m]; memory[m] = TRUE;]
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
No caso dos CPU x86 o opcode LOCK é aplicado às instruções aasembly indicadas
em cima.
19
6.19 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SoluSoluçção utilizandoão utilizando TestTest--andand--SetSet
� Variável booleana partilhada lock, inicializada a FALSE.� Solução:
while (true) {while ( TestAndSet (&lock ))
; // do nothing
// critical section
lock = FALSE;
// remainder section
}
A SC implementada com o TS têm agora a robustez desejada!
Consegue-se assim implementar uma Secção Crítica.
20
6.20 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SemSemááforosforosSource: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Este é um mecanismo mais sofisticado para sincronização. Ele permite resolver um
outro tipo de problemas (por exemplo produtores e consumidores).
E veremos como ele é implementável à custa da primitiva de sincronização mais
simples, facultada pelo hardware, que é a SC.
21
6.21 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
O Problema do Produtor e Consumidor(1)O Problema do Produtor e Consumidor(1)producer() {
while (true) {item = produceItem()
if (itemCount == BUFFER_SIZE) {
sleep()
}putItemIntoBuffer(item)itemCount = itemCount + 1
if (itemCount == 1) {
wakeup(consumer)
}}
}
consumer() {
while (true) {
if (itemCount == 0) {sleep()
}
item = removeItemFromBuffer()itemCount = itemCount - 1
if (itemCount == BUFFER_SIZE - 1) {wakeup(producer)
}
consumeItem(item)}
}
BUFFER_SIZE=5
22
6.22 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
O problema do Produtor e Consumidor(2)O problema do Produtor e Consumidor(2)
� O produtor depois de produzir um item e incrementar itemCount verifica que o número de itemCount==1 e conclui que o consumidor pode estar a dormir (código a vermelho)
� Porém o consumidor pode ainda não estar a dormir. Ele acabou de fazer o teste, decidiu ir dormir, mas foi comutado antes de chamar o sleep() (código a vermelho)
� Portanto, o wakeup do produtor não encontar ainda ninguém a dormir e perde-se!
� O consumidor finalmente entra no sleep(), mas o respectivo wakeup já foi emitido e não volta a ser repetido (itenCount <>0). Nunca mais acorda!!!
� O código a azul é a situação simétrica e equivalente
� Precisávamos de ter guardado o wakeup!
� O semáforo serve para isso: contabiliza despertares!
23
6.23 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
DefiniDefiniçção ão de de SemSemááforoforo
� A noção de Semáforo foi inicialmente proposta por EdsgerDijkstra em 1968.
� Um semáforo contém um valor inteiro que só pode ser modificado através de duas operações indivisíveis (atómicas):
� Originalmente chamadas P() e V()
� Proberen (testar) e Verhogen (incrementar) em holandês
� O nome das operações evoluíram para
� wait() e signal()
� Mais de acordo com as suas funcionalidades
24
6.24 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
OperaOperaçções sobre um Semões sobre um Semááforoforo
� Definição de P() - wait() e V() - signal()
� atomic wait (S) {
while (S <= 0)
; // wait
S--;
}
� atomic signal (S) {
S++;
}
atomic wait (S) {
waitfor (S > 0);
S = S - 1;
}
Define-se a semântica do wait():
• decrementa o semáforo a menos que ele seja 0 e prosegue. Se é 0 bloqueia.
Mostram-se duas hipotéticas implementações uma com espera activa evidente (esq)
outra em que a espera activa poderá ser evitada.
E do signal():
•que apenas incrementa o semáforo.
Repare-se que a atomicidade das operações tem de ser assegurada!!!
25
6.25 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Ferramenta de SincronizaFerramenta de Sincronizaçção Genão Genééricarica
� Os semáforos podem ser de contagem (counting) ou binários(mutexes)
� Counting -> sincronização de n recursos distintos
� O valor do semáforo é um inteiro entre 0 e N.
� Mutexes -> exclusão mútua de secções críticas
� O valor do semáforo só pode ser 1 ou 0
� O Mutex permite criar exclusão mútua em secções críticas
� Semaphore S; // initialized to 1
� wait (S);
Critical Section
signal (S);
A especilização do semáforo conhecida por mutex é usada para implementar as SC,
pois apresenta para o programador uma API mais homegénea.
26
6.26 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Exemplos de UtilizaExemplos de Utilizaççãoão
semaphore mutex = 1;
fork(proc_0, 0);
fork(proc_1, 0);
proc_0() { proc_1() {
while(TRUE) { while(TRUE {
<compute section>; <compute section>;
wait(mutex); wait(mutex);
<critical section>; <critical section>;
signal(mutex); signal(mutex);
} }
} }
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
Compare-se com o protocolo da SC!
27
6.27 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema do BalanProblema do Balançço de Contao de Conta
semaphore mutex = 1;
shared int balance;
fork(proc_0, 0);
fork(proc_1, 0);
proc_0() { proc_1() {
. . . . . .
/* Enter the CS */ /* Enter the CS */
wait(mutex); wait(mutex);
balance += amount; balance -= amount;
signal(mutex); signal(mutex);
. . . . . .
} }
Source: Operating Systems, Gary NuttCopyright © 2004 Pearson Education, Inc.
28
6.28 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Partilha de 2 VariPartilha de 2 Variááveisveis
� Problema:
� Dois processos P1 e P2 trabalham em cooperação
� Utilizam duas variáveis partilhadas x e y para trocar valores
� Os processos têm de se sincronizar para que os valores das variáveis sejam significativos
� Algoritmo:
� P1 actualiza x e continua a execução
� P2 deve ler o valor posto em x por P1 e actualizar y
� P1 deve esperar que P2 actualize y e ler o seu valor
� Sincronização
� Dois semáforos S1 e S2 associados a x e y
� Os semáforos servem de sincronização entre P1 e P2
� Podem também criar um deadlock se forem mal geridos
O problema da comunicação por memória partilhada! Qdo falamos deste mecanismo
de IPC dissemos que tinha o problema da sincronização. Eis a solução!
Numa mesma máquina os processos de uma mesma máquina usam geralmente
memória partilhada e estes mecanismo para se sincronizarem!
29
6.29 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Partilha de 2 VariPartilha de 2 Variááveis (veis (ContCont.).)
proc_A() {
while(TRUE) {
<compute section A1>;
update(x);
/* Signal proc_B */
signal(s1);
<compute section A2>;
/* Wait for proc_B */
wait(s2);
retrieve(y);
}
}
proc_B() {
while(TRUE) {
/* Wait for proc_A */
wait(s1);
retrieve(x);
<compute section B1>;
update(y);
/* Signal proc_A */
signal(s2);
<compute section B2>;
}
}
semaphore s1 = 0; // Protects x, initially wait
semaphore s2 = 0; // Protects y, initially wait
shared int x, y;
create_thread(proc_A, 0);
create_thread(proc_B, 0);
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
30
6.30 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção de Semão de Semááforosforos
� É preciso garantir que não há mais de um processo a executar wait () e signal () no mesmo semáforo ao mesmo tempo
� A implementação reduz-se ao problema da secção crítica onde os códigos de wait e signal estão dentro da SC
� O semáforo binário pode ser implementado simplesmente com uma instrução Test-and-Set e uma variável binária
� O valor FALSE indica que o semáforo está livre e TRUE ocupado
// Wait definition
boolean s = FALSE;
wait(s) {
while(TS(s))
; // wait
}
// Signal Definition
signal(s) {
s = FALSE;
}
Como é contruído um semáforo? É muito simples! O problema está nos detalhes
e a beleza!
Começamos com o mutex.
Usamos as primitivas que já construimos, o TestAndSet.
Nesta implementação continuamos a fazer espera activa no while.
31
6.31 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção do Semão do Semááforo Genforo Genééricorico
� A implementação de um semáforo com contador é mais complexa e necessita de uma estrutura com três campos:
� O campo mutex permite criar e proteger a secção crítica correspondente à modificação do valor do semáforo
� O campo hold permite colocar o processo (ou thread) em espera no caso do valor do semáforo ser <= 0
� O campo value contém o valor do semáforo (nº de recursos livres) que é negativo no caso de haver processos em espera
� Os campos mutex e hold são modificados através de instruções Test-and-Set
� Um semáforo binário é um semáforo genérico com valor inicial = 1
struct semaphore {
boolean mutex = FALSE;
boolean hold = TRUE;
int value = <initial value>;
};
32
6.32 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção do Semão do Semááforo Genforo Genééricoricostruct semaphore {
int value = <initial value>;
boolean mutex = FALSE;
boolean hold = TRUE;
};
shared struct semaphore s;
wait(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value--;
if(s.value < 0) {
s.mutex = FALSE;
while(TS(s.hold))
; // wait
} else
s.mutex = FALSE;
}
signal(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value++;
if(s.value <= 0) {
while(s.hold == FALSE)
; // wait
s.hold = FALSE;
}
s.mutex = FALSE;
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
Para o aluno se aperceber da importância dos detalhes é útil seguir a lógica:
•Todo o acesso ao contador tem de ser exclusivo
•Se, no wait, passamos o contador abaixo de =, é porque ele estava em 0.
•Logo devemos bloquear (no hold).
• Mas não podemos bloquear antes de sair da SC,
pois de outra forma paravamos os outros processos também!!!
•Mas isso significa que o TS(s.hold) é fora da SC, logo pode haver comutação!!!
• Temos de acrescentar um teste~adcional ao signal() para verificar se houve estacomutação.!!! É o código na zona colorida.
33
6.33 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção do Semão do Semááforo Genforo Genééricoricostruct semaphore {
int value = <initial value>;
boolean mutex = FALSE;
boolean hold = TRUE;
};
shared struct semaphore s;
wait(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value--;
if(s.value < 0) {
s.mutex = FALSE;
while(TS(s.hold))
; // wait
} else
s.mutex = FALSE;
}
signal(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value++;
if(s.value <= 0) {
while(s.hold == FALSE)
; // wait
s.hold = FALSE;
}
s.mutex = FALSE;
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� Race condition:
� No caso em que s.value<=0, a thread em signal() tem de aguardar que haja outra threadem espera em s.hold, pois pode ter entrado em wait(), mas estar no ponto indicado
� Assim seria libertado um recurso antes da outra thread esperar, e perdia-se uma sinalização !
Race condition = corrida crítica.
34
6.34 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Espera ActivaEspera Activa
� Nas implementações de semáforos apresentadas, a operação wait() implica uma espera activa pelo valor positivo do semáforo
� Busy wait ou Spin lock
� O processo testa o valor e caso este seja menor ou igual a zero,volta a testar, continuando a concorrer com os outros processos
� Está a consumir recursos quando não tem condições para se executar
atomic wait (S) {
while (S <= 0)
; // busy wait
S = S - 1;
}
Quando há espera activa (busy wait) estamos a consumir CPU. Poderá ser aceitável
durante um curto intervalo de tempo espacielmente se o processo ou thread tem algo
mais para fazer.
Em SO com mais que em CPU a espera activa pode existir dentro de um wait,
pois o overhead de comutação de processos pode ser superior ao tempo de espera.
35
6.35 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SemSemááforos sem Espera Activaforos sem Espera Activa
� Uma solução mais correcta é pôr o processo em espera através de invocações explícitas do Scheduler
� wait(): retirar o processo da Ready Queue no caso em que o semáforo esteja ocupado
� signal(): voltar a colocar um dos processo em espera na ReadyQueue sempre que haja processos bloqueados
� Assim a espera num semáforo assemelha-se a qualquer outra operação de espera por recursos (p.ex.: I/O)
� Ao semáforo pode ser associada uma fila de espera de processos e duas rotinas:
� sleep() – retira o processo corrente da RQ e coloca-o na fila de espera associada ao semáforo.
� wakeup() – retira um processo da fila de espera do semáforo e volta a inseri-lo na RQ.
� O processo a eleger depende dos critérios de scheduling do sistema
Vemos como o mecanismo para gestão e escalonamento de processos e threads
é reusável para o Kernel implementar semáforos sem espera activa!
36
6.36 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção com Fila de Esperaão com Fila de Espera
struct semaphore {
struct proc *queue;
int value = <initial value>;
boolean mutex = FALSE;
};
shared struct semaphore s;
wait(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value--;
if(s.value < 0) {
s.mutex = FALSE;
sleep(s.queue);
} else
s.mutex = FALSE;
}
signal(struct semaphore s){
while(TS(s.mutex))
; // wait
s.value++;
if(s.value <= 0) {
wakeup(s.queue);
}
s.mutex = FALSE;
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� O wakeup é feito pela primitiva signal() sempre s.value <= 0 ou seja, sempre que haja processos em espera
� Neste caso o recurso é“transferido” do processo que o liberta para um dos processos que está à espera em sleep()
Aqui vemos como a implementação das operações do semáforo se faz com recursos
às chamadas de sistema.
37
6.37 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Deadlock e StarvationDeadlock e Starvation
� Deadlock – dois ou mais processos esperam para sempre por um evento que só um dos processos bloqueados pode produzir
� Se S e Q forem dois semáforos inicializados a 1, a ordem de invocação apresentada conduz a um deadlock
P0 P1
wait (S); wait (Q);
wait (Q); wait (S);
. .
. .
. .
signal (Q); signal (S);
signal (S); signal (Q);
1 2
3 4
Deadlock !
Deadlock é uma situação frequente em aplicações multiprocesso/multithread devido
a erros de concepção e implementação .
38
6.38 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problemas ClProblemas Cláássicos de Sincronizassicos de Sincronizaççãoão
� Problema do Buffer Limitado ou do Produtor e Consumidor
� Problema dos Leitores e Escritores
� Problema do Jantar de Filósofos
Estes problemas não são meramente alegóricos. Eles exemplificam situações bem
Conbcretas.
39
6.39 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ProblemaProblema do Buffer do Buffer LimitadoLimitado
Empty Pool
Full Pool
� Um processo produz dados que outro consome
� Utilizam uma pool de buffers para passar dados de um para o outro
� O produtor pode funcionar enquanto houver buffers vazios, e espera quando estiverem todos cheios, até que um esteja vazio
� O consumidor pode funcionar enquanto houver buffers cheios e espera quando estiverem todos vazios, até que um esteja cheio
ProducerProducer ConsumerConsumerData in Data out
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
40
6.40 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ProblemaProblema do Buffer do Buffer Limitado Limitado (2)(2)semaphore full = 0; /* A general (counting) semaphore */
semaphore empty = N; /* A general (counting) semaphore */
producer() {
while(TRUE) {
produce_item();
/* Get an empty buffer */
wait(empty);
put_item_in_buffer();
/* Signal one more item
is available */
signal(full);
}
}
consumer() {
while(TRUE) {
/* Get a full buffer */
wait(full);
remove_item_from_buffer();
/* Signal an empty buffer */
signal(empty);
consume_item();
}
}
• Solução para 1 consumidor e 1 produtor.
•Para mais produtores as funções put_item_in_buffer() concorrem.
•Necessário esclusão mútua
•Para mais consumidores as funções remove_item_from_buffer() concorrem.
•Necessário exclusão mútua.
41
6.41 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ProblemaProblema do Buffer do Buffer Limitado Limitado (3)(3)
mmúúltiplosltiplos produtores/consumidoresprodutores/consumidoressemaphore mutex = 1;semaphore full = 0;semaphore empty = N;
procedure producer() {while (true) {
produceItem()wait(empty)wait(mutex)putItemIntoBuffer()signal(mutex)signal(full))
}}
procedure consumer() {while (true) {
wait(full)wait(mutex)removeItemFromBuffer()signal(mutex)signal(empty)consumeItem()
}}
Esta implementação assume que existe mais do que um produtor que competem entre
pelos buffers livres e tabém mais do que consumidor que também competem entre si.
Assim torna-se necessário que apenas um produtor aceda ao slot livre; para isso
usa-se o mutex.
42
6.42 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos Leitores e EscritoresProblema dos Leitores e Escritores
Leitores
Escritores
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
43
6.43 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos Leitores e Escritores Problema dos Leitores e Escritores (2)(2)
ReaderReaderReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReader
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriter
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� Um conjunto de processos realizam acessos a um recurso comum, uns para escrever, outros para ler o seu conteúdo
� Ficheiro, BD, …
� É necessário garantir a coerência dos valores
Shared Resource
Shared Resource
44
6.44 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos Leitores e Escritores Problema dos Leitores e Escritores (3)(3)
ReaderReaderReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReader
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriter
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� N leitores podem-se executar simultaneamente
Shared Resource
Shared Resource
45
6.45 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos Leitores e Escritores Problema dos Leitores e Escritores (4)(4)
ReaderReader
Shared Resource
Shared Resource
ReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReaderReaderReader
ReaderReader
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriterWriterWriter
WriterWriter
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� Só um escritor se pode executar de cada vez
� Quando um escritor está activo, os leitores esperam
� Quando há leitores activos, o escritor espera
O estudante deve perceber a natureza do problema e de que forma as primitivas
de sincronização aprendidas servem para o resolver.
46
6.46 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Primeira SoluPrimeira SoluççãoãoresourceType *resource;
int readCount = 0;
semaphore mutex = 1;
semaphore writeBlock = 1;
create_thread(reader, 0);
create_thread(writer, 0);
reader() {
while(TRUE) {
<other computing>;
wait(mutex);
readCount++;
if(readCount == 1)
wait(writeBlock);
signal(mutex);
read(resource);
/* Critical section */
wait(mutex);
readCount--;
if(readCount == 0)
signal(writeBlock);
signal(mutex);
}
}
writer() {
while(TRUE) {
<other computing>;
wait(writeBlock);
/* Critical section */
write(resource);
signal(writeBlock);
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� O primeiro leitor bloqueia os escritores
� O último leitor desbloqueia os escritores
� Qualquer escritor espera por todos os leitores
� Os leitores podem causar starvation dos escritores porque as actualizações “não passam”
� Não é o comportamento mais desejado
Existem 2 soluções: uma dá prioridade aos leitores.
47
6.47 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Segunda SoluSegunda Soluççãoão
� O algoritmo é modificado para privilegiar os escritores
� Os leitores continuam a poder ler sem exclusão mútua
� Se aparece um escritor e está um leitor activo, o escritor espera
� Se um leitor aparece com um escritor em espera, o leitor espera que o escritor saia
� Se um segundo escritor aparece, tem prioridade sobre os leitores que podem esperar indefinidamente
� Esta solução é complexa e necessita uma implementação cautelosa para evitar deadlocks e starvation
� Veremos uma solução mais robusta baseada em monitores
48
6.48 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Prioridade aos EscritoresPrioridade aos Escritoresint readCount = 0, writeCount = 0;
semaphore mutex1 = 1, mutex2 = 1;
semaphore readBlock = 1, writeBlock = 1;
create_thread(reader, 0);
create_thread(writer, 0);
reader() {
while(TRUE) {
<other computing>;
wait(readBlock);
wait(mutex1);
readCount++;
if(readCount == 1)
wait(writeBlock);
signal(mutex1);
signal(readBlock);
read(resource);
wait(mutex1);
readCount--;
if(readCount == 0)
signal(writeBlock);
signal(mutex1);
}
}
writer() {
while(TRUE) {
<other computing>;
wait(mutex2);
writeCount++;
if(writeCount == 1)
wait(readBlock);
signal(mutex2);
wait(writeBlock);
write(resource);
signal(writeBlock);
wait(mutex2)
writeCount--;
if(writeCount == 0)
signal(readBlock);
signal(mutex2);
}
}
12
3
4
5
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
a segunda dá prioridade aos escritores.
49
6.49 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos FilProblema dos Filóósofos sofos àà MesaMesa
� Cinco filósofos estão sentados a uma mesa a comer massa:
� Cada um tem um talher de cada lado, que partilha com o seu vizinho do lado
� Cada um pensa, e só pode comer quando ficam livres os dois talheres de cada lado do prato
� Dois filósofos sentados ao lado um do outro não podem comer ao mesmo tempo.
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
50
6.50 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problema dos FilProblema dos Filóósofos sofos àà MesaMesa
� Para resolver o problema vamos atribuir um índice a cada filósofo, com i variando de 0 a 4
� A cada garfo associa-se um semáforo designado por garfo(i)
� O filósofo i pode comer quando estão livres simultaneamente os semáforos garfo(i) e garfo((i+1) mod 5), ou seja:
� garfo(0) e garfo(1)
� garfo(1) e garfo(2)
� garfo(2) e garfo(3)
� garfo(3) e garfo(4)
� garfo(4) e garfo(0)
51
6.51 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Primeira SoluPrimeira Soluççãoão
semaphore garfo[5] = (1,1,1,1,1);
fork (filosofo, 1, 0);
fork (filosofo, 1, 1);
fork (filosofo, 1, 2);
fork (filosofo, 1, 3);
fork (filosofo, 1, 4);
filosofo (int i) {
while(TRUE) {
// Think
// Eat
P(garfo[i]);
P(garfo[(i+1) % 5]);
eat();
V(garfo[(i+1) % 5]);
V(garfo[i]);
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
garfo(i)
garfo(i+1)
filosofo(i)
52
6.52 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Primeira SoluPrimeira Soluççãoão
semaphore garfo[5] = (1,1,1,1,1);
fork (filosofo, 1, 0);
fork (filosofo, 1, 1);
fork (filosofo, 1, 2);
fork (filosofo, 1, 3);
fork (filosofo, 1, 4);
filosofo (int i) {
while(TRUE) {
// Think
// Eat
P(garfo[i]);
P(garfo[(i+1) % 5]);
eat();
V(garfo[(i+1) % 5]);
V(garfo[i]);
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� Se todos os filósofos acederem simultaneamente aos talheres do mesmo lado (esquerdo ou direito), cria-se uma solução de Deadlock
53
6.53 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Segunda SoluSegunda Soluççãoão
semaphore garfo[5] = (1,1,1,1,1);
fork (filosofo, 1, 0);
fork (filosofo, 1, 1);
fork (filosofo, 1, 2);
fork (filosofo, 1, 3);
fork (filosofo, 1, 4);
filosofo (int i) {
while(TRUE) {
// Think
// Eat
j = i % 2;
P(garfo[(i+j) % 5]);
P(garfo[(i+1-j) % 5]);
eat();
V(garfo[(i+1-j) % 5]);
V(garfo[[(i+j) % 5]);
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
� Na primeira escolha, os filósofos de índice par escolhem o garfo esquerdo, e os de índice ímpar, o garfo direito
� Na segunda escolha inverte-se a ordem
54
6.54 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Segunda SoluSegunda Soluççãoão
semaphore garfo[5] = (1,1,1,1,1);
fork (filosofo, 1, 0);
fork (filosofo, 1, 1);
fork (filosofo, 1, 2);
fork (filosofo, 1, 3);
fork (filosofo, 1, 4);
filosofo (int i) {
while(TRUE) {
// Think
// Eat
j = i % 2;
P(garfo[(i+j) % 5]);
P(garfo[(i+1-j) % 5]);
eat();
V(garfo[(i+1-j) % 5]);
V(garfo[[(i+j) % 5]);
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
garfo(0)
filosofo(1)
garfo(2)
filosofo(0)
filosofo(2)
filosofo(3)
filosofo(4)
garfo(3)
garfo(4) garfo(1)
� Na primeira escolha, os filósofos de índice par escolhem o garfo esquerdo, e os de índice ímpar, o garfo direito
� Na segunda escolha inverte-se a ordem
55
6.55 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Problemas de UtilizaProblemas de Utilizaçção dos Semão dos Semááforosforos
� As operações sobre os semáforos têm de ser usadas correctamente
� Se há troca de ordem, pode haver vários processos na secção crítica
wait (mutex)
// Secção Crítica
signal (mutex)
� Se houver troca de funções, gera-se um deadlock
signal (mutex)
// Secção Crítica
wait (mutex)
� Se houver omissão de uma das funções, um dos dois casos anteriores pode acontecer
� É relativamente frequente em programas complexos acontecerem situações deste tipo que não são fáceis de detectar
� Para evitar estas situações, algumas linguagens utilizam ferramentas de sincronização mais fáceis de utilizar
Motivação para a necessiade de mecanismos mais amigos do programador, que,
não obstante vão ser construídos à custa do que já aprendemos.
56
6.56 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
MonitoresMonitores� Uma extensão do conceito de semáforo de mais alto nível que fornece
uma interface eficaz e fácil de utilizar para sincronização de threadsou processos
� Conceito de programação Orientada aos Objectos
� Embebida nas linguagens Java e Concurrent Pascal
� Gerida pelo compilador
� O monitor encapsula (esconde) a sua implementação
� Só são acessíveis métodos e dados públicos
� Os métodos e dados privados são só utilizador pelo monitor
� O monitor garante exclusão mútua dos processos que o executam:monitor mon {
private:
semaphore mutex = 1; // Implícito
. . .
public:
proc_i(…) {
P(mutex); // Implícito
<code for proc_i>;
V(mutex); // Implícito
};
};
Esta maéria não vem para o tesde de 6/Janeiro.
57
6.57 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ExemploExemplo: Shared Balance: Shared Balance
monitor sharedBalance {
private:
double balance;
public:
credit(double amount){
balance += amount;
}
debit(double amount){
balance -= amount;
}
. . .
}
� O problema da partilha da variável balance é resolvido através da declaração de um monitor contendo:
� Uma variável privada balance
� Dois métodos públicos que são executados no interior do monitor com exclusão mútua implícita
58
6.58 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
RepresentaRepresentaçção de um Monitorão de um Monitor
59
6.59 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
VariVariááveis de Condiveis de Condiççãoão
� Os monitores fornecem também mecanismos que permitem às threads esperar que se verifiquem condições específicas
� Designam-se por Variáveis de Condição
� Geralmente, são definidas duas operações sobre uma VC x
� x.wait () – permite a uma thread que invoca esta operação ser suspensa até a condição se verificar
� x.signal () – permite a uma thread sinalizar o facto de que a condição se verificou, e activar uma das threads que estiverem em espera
� Não é geralmente garantido que a thread activada seja a que mais tempo tenha esperado
� A forma como as threads são reactivadas por x.signal()depende da implementação do monitor e do algoritmo de scheduling
60
6.60 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Um Monitor com VariUm Monitor com Variááveis de Condiveis de Condiççãoão
61
6.61 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Estrutura de um MonitorEstrutura de um Monitor
� Variáveis de Sincronização do Monitor
� Um mutex para exclusão mútua no monitor, inicializado a 1
� Um mutex de sinalização no monitor, inicializado a 0
� Um contador de processos em esperasemaphore mutex = 1; // monitor mutex, initially = 1 semaphore other = 0; // signaling mutex, initially = 0int others_waiting = 0; // number waiting for signaling
� Variáveis de Condição do Monitor: para cada condição éintroduzida uma variável com a seguinte estrutura� Um semáforo de sinalização inicializado a 0� Um contador de processos em espera na variável
struct condvar x {semaphore sem; // initially = 0int count = 0; // waiting on x
};
62
6.62 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção do Monitor ão do Monitor -- 11
� Variável de condição x:struct condvar x {
semaphore sem; // initially = 0int count = 0; // waiting on x
};
� Operação x.wait:x.wait () {
x.count++;if (others_waiting > 0)
signal (other);else
signal (mutex);wait (x.sem);x.count--;
}
� Operação x.signal:x.signal () {
if (x.count > 0) {others_waiting++;signal (x.sem);wait (other);others_waiting--;
}
� Variáveis de sincronização:semaphore mutex = 1; // monitor mutexsemaphore other = 0; // signaling mutexint others_waiting = 0; // waiting for signaling
� As operações sobre a variável de condição são executadas no interior dos métodos do monitor, com o semáforo de exclusão mutextomado
63
6.63 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
ImplementaImplementaçção do Monitor ão do Monitor -- 22
� Cada método M do monitor deve obedecer à seguinte estrutura:
wait (mutex);…código de M;…
if (other_waiting)signal (other);
elsesignal (mutex);
� No caso de um método M invocar no seu interior uma operação de espera ou sinalização de uma variável de condição, e havendo outros processos em espera, deve à saída libertar o semáforo de sinalização e não o de sincronização
64
6.64 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Readers & Writers com Readers & Writers com MonitoresMonitores
monitor readerWriter {
int numberOfReaders = 0;
boolean busy = FALSE;
condition okToRead, okToWrite;
public:
startRead() {
if(busy || (okToWrite.queue())
okToRead.wait();
numberOfReaders++;
okToRead.signal();
}
finishRead() {
numberOfReaders--;
if(numberOfReaders == 0)
okToWrite.signal();
}
startWrite() {
if((numberOfReaders != 0)
|| busy)
okToWrite.wait();
busy = TRUE;
}
finishWrite() {
busy = FALSE;
if(okToRead.queue())
okToRead.signal()
else
okToWrite.signal()
}
}
So
urc
e:
Op
era
tin
g S
ys
tem
s,
Ga
ry N
utt
Co
py
rig
ht
©2
00
4 P
ea
rso
n E
du
ca
tio
n,
Inc
.
65
6.65 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
Exemplos de SincronizaExemplos de Sincronizaççãoão
� Solaris
� Windows XP
� Linux
� Pthreads
66
6.66 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SincronizaSincronizaççãoão emem SolarisSolaris
� Implementa uma grande variedade de locks para suporte de multitasking, multithreading e multiprocessing
� Usa mutexes adaptativos para proteger dados partilhados em segmentos de código curtos
� Comportamento do lock depende de haver ou não vários CPUs
� Utiliza condition variables e readers-writers locks quando as secções de código a proteger são mais extensas
� Utiliza um tipo de fila de espera específico (turnstiles) para ordenar a lista de threads que esperam para adquirir os vários tipos de locks.
67
6.67 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SincronizaSincronizaççãoão emem Windows XPWindows XP
� Em monoprocessador, utiliza desactivação de interrupções para proteger secção críticas curtas
� Utiliza spinlocks em ambiente multiprocessador
� Fornece dispatcher objects que podem funcionar como mutexes e semáforos
� Os Dispatcher objects também podem gerar eventos
� Funcionam como variáveis de condição
68
6.68 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SincronizaSincronizaççãoão emem LinuxLinux
� Em monoprocessador, utiliza a desactivação de interrupções para proteger secção críticas curtas
� Utiliza spinlocks baseados em TAS em ambiente multiprocessador
� O kernel é preemptível desde a versão 2.6, mas quando um processo kernel obtém um lock, esta possibilidade é suspensa através da manutenção de um contador do número de preempções em curso (preempt_count) por processo kernel
� Quando as secções críticas de código são extensas, utilizam-se semáforos
� System call futex() “Fast Userspace muTexes” permite a implementação de mutex e semáforos em modo utilizador com recurso mínimo a funções do kernel
http://lxr.linux.no/linux/kernel/futex.c
69
6.69 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
SincronizaSincronizaççãoão nasnas PthreadsPthreads
� A API das pthreads é independente do Sistema Operativo
� A API fornece:
� mutex locks
� condition variables
� Extensões não dependentes do SO fornecem também:
� read-write locks
� spin locks
70
6.70 Silberschatz, Galvin and Gagne ©2005Operating System Concepts
API API pthreadspthreads para Sincronizapara Sincronizaççãoão
� Gestão de Mutexes
� pthread_mutex_init (mutex,attr)
� pthread_mutex_lock (mutex)
� pthread_mutex_trylock (mutex)
� pthread_mutex_unlock (mutex)
� Gestão de Condition Variables
� pthread_cond_init (condition,attr)
� pthread_cond_wait (condition,mutex)
� pthread_cond_signal (condition)
� pthread_cond_broadcast (condition)
� Utilização
� pthread_cond_wait deve ser invocada com um mutex locked, a função liberta-o implicitamente
� pthread_cond_signal deve ser invocada com um mutex lockedque é necessário libertar para que uma thread que espera possa recomeçar
71
Fim do CapFim do Capíítulo 6tulo 6