2016-07-11 8 views
0

Programm in Ruby passiert:Mutual Exclusion nicht

def inc(n) 
    n + 1 
end 

sum = 0 
threads = (1..10).map do 
    Thread.new do 
     10_000.times do 
      sum = inc(sum) 
     end 
    end 
end 
threads.each(&:join) 
p sum 

Ausgang:

$ ruby MutualExclusion.rb 
100000 
$ 

Meine erwartete Ausgabe von oben Programm ist weniger als 100.000. Weil das obige Programm 10 Threads erstellt und jeder Thread die gemeinsam genutzte Variable 'sum' auf 10.000 Mal aktualisiert. Aber während der Ausführung des Programms wird der gegenseitige Ausschluss definitiv passieren. Denn wechselseitiger Ausschluss wird hier nicht behandelt. Also erwarte ich weniger als 100.000 als Ausgabe. Aber es gibt genau 100.000 als Ausgabe. Wie ist es passiert? Wer kümmert sich hier um den gegenseitigen Ausschluss? Und wie ich dieses Problem (ME) experimentiere.

+0

Haben Sie Ihren Code in MRI oder JRuby testen? – spickermann

+0

@spickermann Nein. Ich bin ein Neuling. Und das war mir nicht bewusst. – mrg

+0

@spickermann das sagte, MRI :) – mudasobwa

Antwort

0

Der Standardinterpreter für Ruby (MRI) führt Threads nicht parallel aus. Der Mechanismus, der verhindert, dass Ihr Race-Zustand zufälliges unerwartetes Verhalten hervorruft, ist die Global Interpreter Lock (GIL).

Sie können mehr darüber erfahren, einschließlich einer sehr ähnlichen Demonstration, hier: http://www.jstorimer.com/blogs/workingwithcode/8085491-nobody-understands-the-gil

+0

Nur ich habe mich geirrt. Glaubst du, dass es richtig ist? Weil es nicht richtig ist, den gegenseitigen Ausschluss zu handhaben, ist es in Ordnung, die Eigenschaft wie 'nur ein Thread kann Ruby-Code zu jeder Zeit ausführen 'zu setzen. Aus diesem Grund wird die parallele Ausführung von Threads vermieden. Dies zerstört den Haupteinsatz von Threads. Was denkst du darüber. Es ist Vor- oder Nachteile zu Rubin? – mrg

+0

@mrg Nicht unbedingt; Es hängt davon ab, was du tust. Besonders beim Erstellen von Web-Services werden Sie eine Menge IO (z. B. API-Anfragen) ausführen. Der Thread-Scheduler kann pausieren, während IO im Hintergrund ausgeführt wird und andere Anfragen in der Zwischenzeit bearbeitet. Für CPU-gebundene Aufgaben wird jedoch ein anderer Interpreter empfohlen (rbx/rubinius ist ziemlich gut). – coreyward

+0

Also soll ich nehmen MRI ist gut für Web-Services und RBX ist gut für cpu-gebundene Aufgabe? – mrg