2015-12-11 2 views
5

Ho un programma multithread che stampa sulla console in centinaia di posti. Purtroppo, invece diMake mette thread-safe

Line 2 
Line 1 
Line 3 

ottengo

Line2Line1 

Line3 

che sto cercando di fare puts thread-safe.


In Python (che non credo ha questo problema, ma supponiamo che lo ha fatto), lo farei

old_print = print 

print_mutex = threading.Lock() 

def print(*args, **kwargs): 
    print_mutex.acquire() 
    try: 
     old_print(*args, **kwargs) 
    finally: 
     print_mutex.release() 

sto provando questo in Ruby,

old_puts = puts 

puts_mutex = Mutex.new 

def puts(*args) 
    puts_mutex.synchronize { 
     old_puts(*args) 
    } 

Ma questo non funziona: "metodo non definito old_puts"


Come posso rendere thread-safe (ad es. non stampare le linee parziali)?

+4

Suggerimento: quando si esegue 'old_puts = puts' si sta implicitamente facendo' old_puts = puts() ' –

risposta

6
alias old_puts puts 

o più moderna:

module MyKernel 
    PutsMutex = Mutex.new 
    def puts(*) 
    PutsMutex.synchronize{super} 
    end 
end 

module Kernel 
    prepend MyKernel 
end 
+2

" modern "= Ruby 2.0+ –

0

La ragione di questo comportamento è che puts chiama internamente la write funzione sottostante due volte - uno per il valore effettivo da scrivere, e uno per il ritorno a capo essere scritto (Spiegato in Ruby's puts is not atomic)

Ecco un trucco per rendere puts chiamata write esattamente una volta: Aggiungere \n alla stringa che si sta scrivendo. Ecco come si presenta nel mio codice:

# Threadsafe `puts` that outputs text and newline atomically 
def safe_puts(msg) 
    puts msg + "\n" 
end 

puts controlla internamente se l'oggetto viene scritto ha una nuova riga alla fine, e chiede solo write ancora se questo non è vero. Dal momento che abbiamo modificato l'input per terminare con una nuova riga, puts termina facendo una sola chiamata a write.