associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

SemaforosDeadlock

Receita: SemaforosDeadlock

Abaixo estão pequenos exemplos do uso de semáforos e como não deixar ocorrer deadlock.

Esses códigos criei para demonstrar os conceitos básicos, para a utilização em um curso de Sistemas Operacionais.

Semáforos para cuidar da Seção Crítica de um Programa

   1 # -*- coding: ISO-8859-1 -*-
   2 
   3 import thread
   4 import time, random
   5 
   6 s = thread.allocate_lock()
   7 
   8 def tempo(i):
   9    t = random.randint(3,7)
  10    print "Processo %i dormindo por %i" %(i, t)
  11    time.sleep(t)
  12 
  13 def thread1():
  14    while True:
  15       print "Processo 1 - Adquirindo semáforo"
  16       s.acquire()
  17       print "Processo 1 - Seção crítica"
  18       tempo(1)
  19       print "Processo 1 - Liberando semáforo"
  20       s.release()
  21       print "Processo 1 - seção não crítica"
  22       tempo(1)
  23 
  24 def thread2():
  25    while True:
  26       print "Processo 2 - Adquirindo semáforo"
  27       s.acquire()
  28       print "Processo 2 - Seção crítica"
  29       tempo(2)
  30       print "Processo 2 - Liberando semáforo"
  31       s.release()
  32       print "Processo 2 - seção não crítica"
  33       tempo(2)
  34 
  35 thread.start_new_thread(thread1, ())
  36 thread.start_new_thread(thread2, ())
  37 
  38 while 1: pass

O programa acima é funcional, mas pode ocorrer travamentos devido a tentativas de acessos simultâneos aos recursos.

Deadlock com Semáforos

   1 # -*- coding: ISO-8859-1 -*-
   2 
   3 import thread
   4 import time, random
   5 
   6 s1 = thread.allocate_lock()
   7 s2 = thread.allocate_lock()
   8 
   9 def tempo(i):
  10    t = random.randint(1,5)
  11    print "Processo %i dormindo por %i" %(i, t)
  12    time.sleep(t)
  13 
  14 def thread1():
  15    print "Processo 1 - Adquirindo semáforo S1"
  16    s1.acquire()
  17    time.sleep(1)
  18    print "Processo 1 - Adquirindo semáforo S2"
  19    s2.acquire()
  20    print "Processo 1 - Seção crítica"
  21    tempo(1)
  22    print "Processo 1 - Liberando semáforos"
  23    s1.release()
  24    s2.release()
  25    print "Processo 1 - seção não crítica"
  26    tempo(1)
  27 
  28 def thread2():
  29    print "Processo 2 - Adquirindo semáforo S2"
  30    s2.acquire()
  31    time.sleep(1)
  32    print "Processo 2 - Adquirindo semáforo S1"
  33    s1.acquire()
  34    print "Processo 2 - Seção crítica"
  35    tempo(2)
  36    print "Processo 2 - Liberando semáforos"
  37    s2.release()
  38    s1.release()
  39    print "Processo 2 - seção não crítica"
  40    tempo(2)
  41 
  42 thread.start_new_thread(thread1, ())
  43 thread.start_new_thread(thread2, ())
  44 
  45 while 1: pass

Problemas Clássicos de Sincronismo

Buffer Limitado

   1 # -*- coding: ISO-8859-1 -*-
   2 import thread
   3 import time, random
   4 import threading
   5 
   6 class BufferLimitado:
   7    TAM_BUFFER = 5
   8    mutex  = threading.Semaphore(1)
   9    empty  = threading.Semaphore(TAM_BUFFER)
  10    full   = threading.Semaphore(0)
  11    buffer = range(TAM_BUFFER)
  12    cheio  = 0
  13    livre  = 0
  14 
  15    def insert(self, item):
  16       self.empty.acquire()
  17       self.mutex.acquire()
  18       self.buffer[self.livre] = item
  19       self.livre = (self.livre + 1) % self.TAM_BUFFER
  20       self.mutex.release()
  21       self.full.release()
  22 
  23    def remove(self):
  24       self.full.acquire()
  25       self.mutex.acquire()
  26       item = self.buffer[self.cheio]
  27       self.cheio = (self.cheio + 1) % self.TAM_BUFFER
  28       self.mutex.release()
  29       self.empty.release()
  30       return item
  31 
  32 b = BufferLimitado()
  33 
  34 def produtor():
  35    while True:
  36       time.sleep(random.randint(1, 10) / 100.0)
  37       item = time.ctime()
  38       b.insert(item)
  39       print "Produtor produziu:", item, b.livre, b.cheio
  40 
  41 def consumidor():
  42    while True:
  43       time.sleep(random.randint(1, 10) / 100.0)
  44       item = b.remove()
  45       print "Consumidor consumiu:", item, b.livre, b.cheio
  46 
  47 thread.start_new_thread(produtor, ())
  48 thread.start_new_thread(consumidor, ())
  49 
  50 while 1: pass

Leitores-Escritores

   1 # -*- coding: ISO-8859-1 -*-
   2 import thread
   3 import time, random
   4 import threading
   5 
   6 class BancoDados:
   7    contLeitor = 0
   8    mutex      = threading.Semaphore(1)
   9    bd         = threading.Semaphore(1)
  10 
  11    def acquireReadLock(self):
  12       global contLeitor
  13       self.mutex.acquire()
  14       self.contLeitor += 1
  15 
  16       # É o primeiro leitor?
  17       if self.contLeitor == 1:
  18          self.bd.acquire()
  19 
  20       self.mutex.release()
  21 
  22    def releaseReadLock(self):
  23       global contLeitor
  24       self.mutex.acquire()
  25       self.contLeitor -= 1
  26 
  27       # É o último leitor?
  28       if self.contLeitor == 0:
  29          self.bd.release()
  30 
  31       self.mutex.release()
  32 
  33    def acquireWriteLock(self):
  34       self.bd.acquire()
  35 
  36    def releaseWriteLock(self):
  37       self.bd.release()
  38 
  39 bd = BancoDados()
  40 
  41 def escritor(e):
  42    while True:
  43       time.sleep(random.randint(1, 5))
  44       bd.acquireWriteLock()
  45       print "Escritor %i - escrevendo..." %e
  46       time.sleep(random.randint(1, 5))
  47       bd.releaseWriteLock()
  48       print "Escritor %i - parou de escrever." %e
  49 
  50 def leitor(l):
  51    while True:
  52       time.sleep(random.randint(1, 10))
  53       bd.acquireReadLock()
  54       print "Leitor %i - lendo..." %l
  55       time.sleep(random.randint(1, 5))
  56       bd.releaseReadLock()
  57       print "Leitor %i - parou de ler." %l
  58 
  59 for i in range(2):
  60    print "Escritor", i
  61    thread.start_new_thread(escritor, tuple([i]))
  62 for i in range(3):
  63    print "Leitor", i
  64    thread.start_new_thread(leitor, tuple([i]))
  65 
  66 
  67 while 1: pass

Filósofos na Mesa de Jantar

   1 # -*- coding: ISO-8859-1 -*-
   2 import thread
   3 import time, random
   4 import threading
   5 
   6 garfo = list()
   7 for i in range(5):
   8    garfo.append(threading.Semaphore(1))
   9 
  10 def filosofo(f):
  11    f = int(f)
  12    while True:
  13       # garfo da esquerda
  14       garfo[f].acquire()
  15       # garfo da direita
  16       garfo[(f + 1) % 5].acquire()
  17       print "Filósofo %i comendo..." %f
  18       time.sleep(random.randint(1, 5))
  19       garfo[f].release()
  20       garfo[(f + 1) % 5].release()
  21       print "Filósofo %i pensando..." %f
  22       time.sleep(random.randint(1, 10))
  23 
  24 for i in range(5):
  25    print "Filósofo", i
  26    thread.start_new_thread(filosofo, tuple([i]))
  27 
  28 while 1: pass

Volta para CookBook.


MarcioMinicz