Problem with Python Thread Print

Asked

Viewed 234 times

1

I’m developing a python code for the philosophers' dinner... for those who don’t know, follow the link: https://blog.pantuza.com/artigos/o-jantar-dos-filosofos-problema-de-sincronizacao-em-sistemas-operacionais... In this case, I’m using threads and semaphore to solve the problem... My question is when printing, because sometimes, is printing a philosopher on top of the other, as shown in the image below... I was wondering if you had a solution for that. Follow the code, and the one just below the code, the terminal image.

import thread
import time, random
import threading

garfo = list()
for i in range(5):
   garfo.append(threading.Semaphore(1))

def filosofo(f):
   f = int(f)
   while True:
      # garfo da esquerda
      garfo[f].acquire()
      # garfo da direita
      garfo[(f + 1) % 5].acquire()
      i = random.randint(1, 5)
      print ("Filosofo %i comendo por %i segundos..." %(f,i))
      time.sleep(i)
      garfo[f].release()
      garfo[(f + 1) % 5].release()
      t = random.randint(1, 10)
      print ("Filosofo %i pensando por %i segundos..."%(f,t))
      time.sleep(t)


for i in range(5):
   print ("Filosofo",i,"iniciado")
   thread.start_new_thread(filosofo, tuple([i]))

while 1: pass

Print do terminal rodando

  • You put that while 1: pass pro program does not terminate before completing the algorithm?

  • 2

    It is important within the while 1: of the end put a time.sleep() m, else athread main will consume 100% CPU making nothingness. (Battery, power, CPU temperature thank)

1 answer

2

Create your own print function that uses a thread lock - that’s enough.

print_lock = threading.Lock()

original_print = __builtins__.print

def print(*args, **kw):
   with print_lock:
      original_print(*args, **kw)

And use that print there in the code that runs in multiple threads.

If there were the possibility of this code generating a "Dead lock": someone waiting to print, but the print will not be released because someone has another lock, then the thing could be more sophisticated -

It would be possible, for example, to have a Queue de print - a fun~ao of "print" called threads would put the print parameters in that Queue, like a tuple, and, in a single thread, you would have a "print" function real that would read the parameters of this Queue and call the original Python print. But it also requires you to have a scheduling mechanism that regularly calls the "print" function on the right thread to check for impressions - or, simpler would be to have a unique loop print thread

stop_printing = object()
print_queue = queue.Queue()

def tprint(*args, **kw):
   print_queue.put((args, kw)) # Coloca args e kw como uma única tupla

def printer_worker():

    while True: 
       parametros = print_queue.get()
       if parametros is stop_printing:
           break
       print(*paramtros[0], **parametros[1])
       time.sleep(0.1)  # pausa é opcional, por que a chamada ao .get é bloqueante. mas é de bom tom - pode ser bem menor, se necessário.

printer = threading.Thread(target=printer_worker)
printer.start() 

In this code, the other threads print using "tprint" instead of "print" (but it is possible to rename the functions as in the other example, of course)

updating: To better understand what happens to the print in the original, see Maniero’s response here: /a/18802/500

Browser other questions tagged

You are not signed in. Login or sign up in order to post.