Parallele Programmierung: volatile Variable nimmt ungewöhnlichen Wert an

Mujahiddin

Top Contributor
Hallo Spezialisten!

Folgendes Programm ist gegeben:

Java:
import java.util.Arrays;
import java.util.concurrent.CyclicBarrier;


public class RandomNumGen {
	
	int d0, d1, d3;
	volatile int dv2, dv4, dv5;
	final CyclicBarrier barrier = new CyclicBarrier( 2 );
	final int[] digits = new int[6];
	
	public class Thread1 extends Thread {
		
		@Override
		public void run() {
			try {
				
				barrier.await();
				
				d0++;
				d1++;
				
				dv2++;
				
				d3 = 9;
				
				barrier.await();
				
				for( int i = 0; i < 4; i++ ) {
					dv4++;
				}
				
				barrier.await();
				
				barrier.await();
				dv5 = 7;
			} catch( Exception e ) {}
		} // END OF run
	} // END OF Thread1
	
	public class Thread2 extends Thread {
		
		@Override
		public void run() {
			try {
				
				barrier.await();
				digits[ 1 ] = d1;
				digits[ 0 ] = d0;
				
				digits[ 2 ] = dv2;
				
				barrier.await();
				digits[ 3 ] = d3;
				
				for( int i = 0; i < 4; i++ ) {
					dv4++;
				}
				
				barrier.await();
				digits[ 4 ] = dv4;
				
				barrier.await();
				dv5 = 5;
			} catch( Exception e ) {}
		} // END OF run
	} // END OF Thread2
	
	public int[] getDigits() {
		d0 = 0;
		d1 = 0;
		d3 = 0;
		dv2 = 0;
		dv4 = 0;
		dv5 = 0;
		Thread t1 = new Thread1();
		Thread t2 = new Thread2();
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
			digits[ 5 ] = dv5;
		} catch( Exception e ) {}
		return digits;
	}
} // END OF RandomNumGen

Die Aufgabe besteht nun darin, dieses Programm zu analysieren und bei dem Array
Code:
getDigits()
, das auf 6 Feldern (0 - 5) besteht, die verschiedenen Möglichkeiten finden und begründen.

Zwei Fragen, die ich mir stelle (in der Vorlesung wurde dazu was gesagt, aber ich kann dem Dozent nicht blindlings vertrauen...):

1. Können die Werte
Code:
digits[0]
und
Code:
digits[1]
4 unterschiedliche Kombinationen an Werten von 0 und 1 annehmen?
Wenn man diesen Code ohne mehr oder weniger "tiefgründiges" Wissen liest, müsste man ja sagen, dass es 3 Möglichkeiten gibt: 0|0, 1|0, 1|1 (ist ja hoffentlich klar)
Ist aber auch 0|1 möglich? In der Vorlesung wurde gesagt, dass es dem Compiler (oder der JVM) überlassen ist, ob
Code:
d0++;
vor
Code:
d1++;
ausgeführt wird, er könne diese auch einfach umtauschen, da die Instruktionen nicht voneinander abhängen. Stimmt das? Wenn ja, liegt es am Compiler oder an der JVM? (Ich habe in meiner Zeit hier im Forum auch öfter mal den Begriff HotSpot gehört, wenn es um solche/ähnliche Sachen ging)

2. digits[4] (hier der Code, der dies betrifft):
Thread1:
Java:
for( int i = 0; i < 4; i++ )
	dv4++; //volatile int dv4;
Thread2:
Java:
for( int i = 0; i < 4; i++ )
	dv4++;
barrier.await();
digits[ 4 ] = dv4;

Ich habe hierzu schon Gedanken gemacht:
Für digits[4] können alle Werte von 2 bis 8 stehen.
Wenn man das an einem Extrembeispiel festmacht, wird es vielleicht klar, und wenn ich irgendwo falsch liege, könnt ihr mich ja verbessern:

Code:
Thread1 zieht den Wert dv4, welcher 0 ist, in seinen Stack [will Addition ausführen, wird aber genau hier unterbrochen]

Thread2 zieht den Wort dv4, welcher 0 ist, in seinen Stack.
	Er addiert eins drauf und legt 1 in dv4 rein.
	Er liest dv4 (1) aus.
	Er schreibt 2 in dv4 rein.
	Er liest dv4 (2) aus.
	Er schreibt 3 in dv4 rein.

Thread1 schreibt 1 in dv4 rein.

Thread2 liest dv4 (1) aus.

Thread1 liest dv4 (1) aus.
	Er schreibt 2 in dv4 rein.
	Er liest dv4 (2) aus.
	Er schreibt 3 in dv4 rein.
	Er liest dv4 (3) aus.
	Er schreibt 4 in dv4 rein
	Er stößt auf den Barrier und wartet...

Thread2 schreibt 2 in dv4 rein und wartet am Barrier.

Thread2 schreibt dv4 (2) in digits[ 4 ].

Das wäre jetzt das Extrembeispiel für 2 in digits[ 4 ]...
Ich hoffe, ich habe das mit Stack und Heap richtig verstanden (danke Ark 🙂)

Also die zweite Frage ist, ob ich damit richtig liege! Könnte auch 1 möglich sein oder liege ich gar völlig falsch? Eclipse hat mir einmal 3 ausgegeben für digits[4].

Liebe Grüße und danke im Voraus,

Mujahiddin.

[EDIT]Ich sehe gerade, der Threadtitel ist ziemlich irreführend... Den hatte ich anfangs drinstehen und während ich schrieb, fiel mir ein, warum diese "ungewöhnlichen" Werte (in diesem Fall 3 für digits[4]) angenommen wurden... Vergaß, den Titel zu ändern![/EDIT]
 
Zuletzt bearbeitet:
>>>Wenn man diesen Code ohne mehr oder weniger "tiefgründiges" Wissen liest, müsste man ja sagen, dass es 3 Möglichkeiten gibt: 0|0, 1|0, 1|1 (ist ja hoffentlich klar)

Es sind 4 Möglichkeiten:
0|0, 0|1, 1|0, 1|1

Pentalon
 
>>>Wenn man diesen Code ohne mehr oder weniger "tiefgründiges" Wissen liest, müsste man ja sagen, dass es 3 Möglichkeiten gibt: 0|0, 1|0, 1|1 (ist ja hoffentlich klar)

Es sind 4 Möglichkeiten:
0|0, 0|1, 1|0, 1|1

Pentalon

Das ist gerade die Frage... Warum ist 0|1 (wenn überhaupt) möglich? Liegt das am JVM oder am Compiler, also stimmt, was der Dozent meinte?
 

Neue Themen


Zurück
Oben