2010-09-26 3 views
9

Ich bin bereit für die SCJP, und Multithreading war meine am meisten wackeligen Bereich, vor allem, weil ich nicht weiß, wie man Multithreading-Code betrachten und durch sie gehen. Bis jetzt war mein Ansatz, auf Englisch aufzuschreiben, was in jedem Thread passieren könnte, und einige Fälle mit Threads zu testen, die sich zufällig überschneiden, was ein wirklich hit-and-miss und zeitraubender Ansatz ist. Also würde ich gerne sehen, wie ein Profi das machen würde. Würdest du bereit sein, den Code unten zu lesen (es ist die letzte Frage, die mir Probleme macht) und aufzuschreiben, was durch deinen Kopf geht (bitte nur Code-bezogenes Zeug :), während du die möglichen Ausgaben ausarbeitest? Die Entscheidungen, die mit der Frage kommen, sind am Ende. Was ich suche, ist nicht die Lösung, die ich habe, sondern wie man effizient zur Lösung auf die Prüfung kommt.Wie denkst du über die Ergebnisse einer Threading-Frage nach?

Und ja, ich weiß, diese Frage keine genaue Antwort hat, etc etc. Accepted Stimme geht an die Antwort, die klarste und einfachste ist zu emulieren, okay :)

Danke an alle!

Frage: Welche dieser Antworten sind mögliche Ergebnisse?

public class Threads1 { 

    int x = 0; 

    class Runner implements Runnable { 

     public void run() { 
      int current = 0; 
      for (int i = 0; i < 4; i++) { 
       current = x; 
       System.out.print(current + ", "); 
       x = current + 2; 
      } 
     } 
    } 

    public static void main(String[] args) { 
     new Threads1().go(); 
    } 

    public void go() { 
     Runnable r1 = new Runner(); 
     new Thread(r1).start(); 
     new Thread(r1).start(); 
    } 
} 

Auswahl (Auswahl all zutreffenden):

A. 0, 2, 4, 4, 6, 8, 10, 6,

B. 0, 2, 4, 6 , 8, 10, 2, 4,

C. 0, 2, 4, 6, 8, 10, 12, 14,

D. 0, 0, 2, 2, 4, 4, 6 , 6, 8, 8, 10, 10, 12, 12, 14, 14,

E. 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14,

+0

Also was ist die Antwort Anita? Ich würde gerne deine Antwort sehen, bevor ich dir meine Denkweise über das Problem gebe. – Gray

+1

Visualisierung ist der Schlüssel, machen Sie Ihre eigene Diagrammtechnik, genug um zu zeigen, was gleichzeitig passiert und welche Ressourcen zwischen den einzelnen Threads geteilt werden. –

+0

Ich habe die Antwort nicht gegeben, weil das zu einfach wäre :) Ehrlich gesagt, wenn ich die Antwort kenne, kann ich erklären, warum es richtig ist, aber es wird herausgefunden, was es überhaupt ist und was ich tun muss kann noch nicht tun. –

Antwort

11

A und C (die Frage der Annahme ist Welche dieser Antworten sind möglich Ausgänge?)

Der schwierige Teil, ist natürlich nicht, wenn Sie eine mögliche Lösung zu finden. Aber, es ist schwer zu sehen, diejenigen, die Sie denken, sind nicht möglich und versuchen, sich davon zu überzeugen, dass Sie einen soliden Grund haben, warum es nicht möglich ist und, dass Sie alle Möglichkeiten beseitigt haben, um zu umgehen Grund.

Bisher mein Ansatz in Englisch zu aufschreiben hat, was in jedem Thread passiert sein könnte ...

Sie müssen herausfinden, welchen Thread jede Nummer gedruckt. Unten ist das effizienteste, prägnanteste Format, das ich mir vorstellen könnte, das darzustellen und es einfach zu machen, Cross-Out/Erase/Write-Over zu verwenden, während Sie die Möglichkeiten durcharbeiten. Erkenne:

  • Sobald Sie eine mögliche Antwort Schachzug finden. Es spielt keine Rolle, ob dies in der realen Welt wahrscheinlich ist oder ob es andere mögliche (oder unmögliche) Kombinationen gibt. Solange Sie 1 Möglichkeit gefunden haben, müssen Sie auf verschieben.

  • Versuchen Sie zuerst den einfachsten Ansatz, z. nehme T1 für jede Zahl an, bis du eine Zahl triffst, die nicht T1 sein könnte, also füllst du T2 aus, und so weiter. Hoffentlich kommst du ohne Widerspruch (oder Widersprüche, die leicht zu lösen sind) ans Ende. Sobald Sie eine mögliche Kombination gefunden haben, fahren Sie fort.

  • Fühlen Sie sich frei, um überspringen die möglichen schnell zu überspringen, damit Sie sich auf die wahrscheinlich unmöglichen konzentrieren können.

Hier ist die letzte Bearbeitung meiner kratz Papier/Arbeitsblatt (mit meiner mentalen Anmerkungen angefügt):

A. 0, 2, 4, 4, 6, 8, 10, 6, 
    1 1 1 2 2 2 2 1  <- possible threads that produced this output - possible solution 

B. 0, 2, 4, 6, 8, 10, 2, 4, 
    1 2 2 2 2 ? 1  <- to print second '2', T1 interrupted between L10/L11; 4 passes of T2 used up 

C. 0, 2, 4, 6, 8, 10, 12, 14, 
    1 1 1 1 2 2 2 2 <- possible solution - simplest solution (T2 waits until T1 is completely done) - doesn't matter that it isn't likely, just that is possible 

D. 0, 0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 
    1 2 1 2 1 2 1 2 1 2 ? <- threads used up 

E. 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14, 
    1 1 1 1 2 2 2 2 ? <- threads used up 

Hinweis:

http://download.oracle.com/javase/tutorial/essential/concurrency/atomic.html

  • Liest und Schreibvorgänge sind atomar für Referenzvariablen und für die meisten primitiven Variablen (alle t ypes außer lang und doppelt).
  • ...

Atomic Aktionen können nicht verschachtelt werden, so können sie ohne Angst vor Faden Interferenz verwendet werden.

+1

+1 Gut ausgeklügelte Logik – linuxuser27

+1

netter Trick zu lösen – Netro

+1

@BerF können wir so denken: Unabhängig von der Ausführung der Threads, müssen die meisten 8 Zahlen gedruckt sein, damit D und E nicht produziert werden können Dieses Beispiel und dann, um Ihre Gedanken für A, B und C zu verwenden? – Xelian

5

Meine Herangehensweise an Multithreading-Probleme ist, aufzubrechen der Code, den der Thread ausführen wird, und dann bestimmen, wie viele Threads diesen Code ausführen und ob auf Variablen zugegriffen wird, die andere Threads möglicherweise verwenden könnten.

In dem Beispiel gibt es 3 Threads. Der main Thread ruft new Threads1().go(); auf, erstellt r1 und startet 2 weitere Threads, new Thread(r1).start(); und new Thread(r1).start();. Jetzt wissen wir, wie viele Threads wir verfolgen können, was sie tun werden.

Der Thread main wird sterben, nachdem er von go() zurückkehrt.

Die anderen 2 Threads werden jeweils die run() Methode des Runner Objekts, r1, eingeben. Nun wissen wir auch, dass jeder Thread run() ausführt. Schauen wir uns an, was run() tut. Es verfügt über eine for-Schleife, die bei jeder Ausführung der Schleife die Ausgabe druckt. Daher wird der Anruf an run()4 mal drucken. So werden 2 Threads pro Thread 4 mal gedruckt. Daher kann die Ausgabe nicht mehr als 8 Nummern haben.

In Bezug auf, was diese Ziffern werden nicht wirklich möglich sein würde, da die Runner Instanz das gleiche für jeden Thread wird die x Variable können auf dem anderen Thread basierend ändern, die auch run() anruft. Sie müssen also nur bestimmen, ob die Ziffernfolge möglich ist. Die Antwort auf diese Frage lautet "Ja" für A und C.Dies ist aufgrund der Tatsache, dass Sie keine Ahnung haben, wenn jeder Thread von der anderen vorweggenommen wird und da während der Schleife eine lokale Kopie erstellt wird, könnten Sie einige sehr eindeutige Ordnungen erhalten.

Wie unten von SB die Option B erwähnt, obwohl es 8 Ausgänge hat, ist es nicht möglich. Versuchen Sie es und erstellen Sie eine Thread-Sequenz, um diese Ausgabe zu erstellen.

+2

wie ist es ja für B? –

+0

Oh wow. Das ist ein guter Ruf. Mein Fehler. Ich werde das korrigieren. Großer Fang. – linuxuser27

+0

Die Antwort könnte A, B oder sogar C sein, abhängig davon, welche Priorität jeder Thread hat und wann jeder Befehl ausgeführt wird. Meine beste Schätzung wäre, A zu beantworten, da es die einzige Antwort ist, die einige sich wiederholende Zahlen interlaced anzeigt, was bedeutet, dass beide Threads parallel ausgeführt werden. Aber jeder der ersten 3 könnte gerechtfertigt sein. –

0

Diese Frage ist viel trügerischer als es aussieht - ich mag es, je mehr ich darüber nachdenke.Ich begann meine Antwort darüber, wie ich Thread-Programme betrachte - ich analysiere die Synchronisationspunkte und die I/O-Aufrufe. Aber das hat keine außer der println, die keine interne Synchronisation hat. Wir haben also ein zufälliges Timing (siehe race conditions). Dies kombiniert mit keiner garantierten Möglichkeit, die Werte von x zwischen den Threads zu synchronisieren bedeutet, dass es zufällig sein wird.

Wenn wir jedoch die Antworten betrachten, können wir sehen, dass einige der Antworten nicht auftreten können. Zum Beispiel, wie @ linuxuser27 darauf hingewiesen hat, druckt jeder Thread nur 4 Zahlen aus, die Antworten entfernen, werden mehr Zahlen gedruckt. Ein anderes Beispiel für eine unpassende Antwort wäre, wenn eine der Antworten einen Wert größer als 14 hätte, da der erste Thread 0,2,4,6 gehen könnte und der zweite 8,10,12,14 aber nicht höher.

Da jeder der Fäden eine Zahl 4 mal und Zahlen, die durch jeden Thread gedruckten Druck muss mindestens muss die vorherige Zahl sein 2+ der Faden gedruckt, einige der Muster nicht erzeugt werden kann. Ich werde meine Antwort nicht geben, aber es ist nicht "alles von oben" und es ist nicht A, B und C.

+0

'jede der Zahlen muss mindestens 2+ der vorherigen Zahl sein, die sie gedruckt haben 'Ich dachte es auch, und ich lag falsch :( –

+1

Wenn t2 mehr als t1 vorrückt, wird t2' current' größer sein als t1 'current', Wenn also t1 die CPU von t2 zurücknimmt, nimmt x den niedrigeren "Strom" von t1 an, und der niedrigere "Strom" wird nach dem höheren gedruckt. So kann die Ausgabe immer noch sinken. –

+0

Ich habe meine Antwort bearbeitet Ich meine, ist, dass die Zahl von t1 immer um mindestens 2 von dem, was zuvor gedruckt wurde, t1 und t2-Nummer auch steigt. – Gray

Verwandte Themen