2013-07-20 4 views

risposta

8

array è la variabile del programma quando si applica un'operazione come << ad esso. Succede in tre passi:

  • La variabile viene prima copiata in un registro CPU.
  • La CPU esegue calcoli.
  • La CPU scrive il risultato nella memoria variabile.

Quindi questa operazione singola di alto livello viene eseguita in tre passaggi. Tra questi passaggi, a causa della commutazione del contesto dei thread, altri thread potrebbero leggere lo stesso valore (vecchio) della variabile. Ecco perché non è un'operazione atomica.

+1

potresti leggere: [** Operazioni atomiche in Ruby **] (http://moonbase.rydia.net/mental/blog/programming/atomic-operations-in-ruby.html) –

+1

hai letto Questo? [Aggiornato con il commento di Jörg su Sept 2011] (http://stackoverflow.com/questions/56087/does-ruby-have-real-multithreading/57802#57802) –

+0

@ theTinMan Un sacco di ringraziamenti! il mio inglese è scarso :(ma noto attentamente la tua e precedente modifica alla mia risposta migliorerò nella prossima risposta Grazie! –

1

Perché Ruby è un linguaggio di livello molto alto, niente è davvero atomico a livello di sistema operativo. Solo operazioni di assemblaggio molto semplici sono atomiche a livello di SO (dipende dal sistema operativo) e ogni operazione Ruby, anche una semplice 1 + 1 corrisponde a centinaia o migliaia di istruzioni di assemblaggio eseguite, come ricerche di metodi, garbage collection, inizializzazione di oggetti, calcoli di scope, ecc.

Se è necessario eseguire operazioni atomiche, utilizzare Mutex.

6

Se più thread accedono allo stesso array, utilizzare la classe integrata di Ruby Queue. Gestisce bene produttori e consumatori.

Questo è l'esempio dalla documentazione:

require 'thread' 

queue = Queue.new 

producer = Thread.new do 
    5.times do |i| 
    sleep rand(i) # simulate expense 
    queue << i 
    puts "#{i} produced" 
    end 
end 

consumer = Thread.new do 
    5.times do |i| 
    value = queue.pop 
    sleep rand(i/2) # simulate expense 
    puts "consumed #{value}" 
    end 
end 

consumer.join 
5

realtà usando la risonanza magnetica (implementazione Ruby Matz) GIL (Global Interpreter Lock) fa alcuna C-pura funzione atomica.

Poiché Array#<< è implementato come codice C puro in MRI, questa operazione sarà atomica. Ma nota questo si applica solo alla risonanza magnetica. Su JRuby questo non è il caso.

di comprendere a fondo ciò che sta accadendo vi consiglio di leggere questi due articoli, che spiega tutto molto bene:

Nobody Understands the GIL
Nobody Understands the GIL - part 2

0

Proprio riffing off di @Linuxios e @TheTinMan: di alto livello le operazioni di linguaggio (HLL) in generale non sono atomiche. L'atomicità è (generalmente) non un problema nei programmi a thread singolo.Nei programmi multi-threaded, tu (il programmatore) devi ragionare su una granularità molto più alta di una singola operazione HLL, quindi avere le singole operazioni HLL che sono atomiche in realtà non ti aiuta molto. Il rovescio della medaglia, anche se fare un'operazione atomica richiede solo poche istruzioni prima e dopo lo — almeno sull'hardware moderno — sommate le spese generali statiche (dimensione binaria) e dinamiche (tempo di esecuzione). Ancor peggio, l'atomicità esplicita disabilita praticamente tutta l'ottimizzazione perché i compilatori non possono spostare le istruzioni attraverso le operazioni atomiche. Nessun vantaggio reale + costo significativo = non-starter.