Synchronized-Schlüsselwort bei Inkrementierung einer statischen Variable

Shams

Aktives Mitglied
Ich habe hier 2 Threads und will jeweils eine statische Variable von 0 nach 99 inkrementieren.

Java:
import java.io.*;

public class Main implements Runnable
{
	
	public static int count = 0;
	
	public int getCount() {
		return count;
	}


	 
	public synchronized void increment(){
		
        int zahl = getCount();
		
     while(zahl<100){
    	 System.out.println(zahl);
        zahl++;
     }
        
		
	}

	@Override
	public void run() {		
		increment();
	  }
 
	
	public static void main(String[] args) 
	{

      Main m1 = new Main();
      m1.run();
      
      Main m2 = new Main();
      m2.run();
    }


       
	 
}

Nun meine Frage: Ist dies mit dem Schlüsselwort "synchronized" auch dann threadsafe, wenn die zu inkrementierende Variable statisch ist? Oder kann es passieren, dass der zweite Thread irgendwann auf die bereits durch den ersten Thread inkrementierte Variable zugreifen könnte?
 

Admiral Helmut

Aktives Mitglied
ich glaube du wirst folgendes Problem kriegen.

Du vermischt static mit objectbezogen.

Mit dem synchronized auf eine Object Methode sicherst du den "Schlüssel des Objects".
D.h. es kann nur ein Thread gleichzeitig eine synchronised Methode DIESES Objekts aufrufen. NIcht mehr nicht weniger.
Es können zum Beipiel in 2 verschiedenen Objekten gleichzeitig die synchronized Methode aufgerufen werden. Und das machst du hier.
Damit ist nicht gesichert, dass nicht 2 Threads auf ein static Feld der Klasse zugreifen.

Ich denke du solltest eher so vorgehen. Du erstellst eine Datenklasse mit einem NICHT static Counter. Diese Klasse sollte dann auch eine synchronized Increment Methode haben.

Jetzt erstellst du dir noch eine Thread Klasse die im Konstruktor das Datenobjekt bekommt und sichert. und in einer Methode die Incrementmethode der Datenklasse aufruft.

In der Main erstellst du ein Datenobjekt und 2 ThreadKlassenobjekte. Diesen gibst du dann bei new das Datenobjekt mit.
Dann bist du Threadsafe.

Bitte verbessert mich wenn ich was falsches sage.

Gruß Helmut
 
Zuletzt bearbeitet:

Joose

Top Contributor
Java:
public synchronized void increment(){	
        int zahl = getCount();	
     while(zahl<100){
    	 System.out.println(zahl);
        zahl++;
     }	
}

Gerade dieser Teil ist auch sehr unsinnig irgendwie.
Durch das "synchronized" blockierst du für andere Aufrufer die Methode.
Der 1.Thread zählt nun gemütlich hoch, wenn dieser fertig ist dann kommt der 2.Thread und hat nichts mehr zu tun ;)

Was du glaub ich willst: Eine Methode welche deine Schleife enthält und innerhalb der Schleife rufst du eine "synchronized" Methode auf die nichts anderes macht als deinen Zähler zu inkrementieren.
 

Shams

Aktives Mitglied
Java:
import java.io.*;

public class Main implements Runnable
{
	
	public static int count = 0;
	
	public int getCount() {
		return count;
	}


	 
	public synchronized void increment(){
		
        int zahl = getCount();
         zahl+=9;
         System.out.println(zahl);
     
        
		
	}

	@Override
	public void run() {		
		increment();
	  }
 
	
	public static void main(String[] args) 
	{

      Main m1 = new Main();
      Main m2 = new Main();
      
      do{
      m1.run();
      m2.run();
       }while(true);
    }	 
}

Vielleicht ist es so etwas sinnvoller, in der Tat, also die Frage ist, ob es passieren kann, dass nicht immer wieder die 9 ausgedruckt wird, sondern auch mal 18 dastehen kann, weil trotz synchronized eine bereits auf den Wert 9 inkrementierte Variable 9 dann zu 18 gemacht werden kann.
 
Zuletzt bearbeitet:

Shams

Aktives Mitglied
Dann ist dies ein besseres Beispiel:
Java:
import java.io.*;

public class Main implements Runnable
{
	
	public static int count = 0;
	
	public int getCount() {
		return count;
	}

	public void setCount(int z){
		count=z;
	}
	 
	public synchronized void increment(){
		
		while(count<66){
		
        int zahl = getCount();
         zahl++;
        setCount(zahl);
         System.out.println(zahl);
     
		} 
		
	}

	@Override
	public void run() {		
		increment();
	  }
 
	
	public static void main(String[] args) 
	{
	      Main m1 = new Main();
      new Thread(m1).start();
      new Thread(m1).start();

    }	 
}
 

Admiral Helmut

Aktives Mitglied
hast du es mal laufen lassen? wird die Reihenfolge vom anderen Thread unterbrochen?

zeig uns mal bitte die Ausgabe.

Die while schleife macht wie Joose schon geschrieben hat kaum einen Sinn.

Ob das mit deinen 2 Main Objekten funktioniert bin ich mir nicht sicher

Gruß Helmut
 
Zuletzt bearbeitet:

Admiral Helmut

Aktives Mitglied
ich glaube du brauchst eher so etwas

Java:
public class Database{
   private int count;
   public Database(){
   count = 0;
}
   public synchronized void increment(){
   count++;
   System.out.println(count);
}


}

Java:
public class Incrementer implements Runnable{
 Database d;
 public Incrementer(Database d){
   this.d = d;
}

public void run(){
for(int i = 0; i<50; i++)
d.increment();
Thread.sleep(1000);
}
}


Java:
public class Main{
   public static void main(String[] args){
Database d = new Database();
 Thread t1 = new Thread(new Incrementer(d));
Thread t2 =new Thread(new Incrementer(d));
t1.start();
t2.start();
}
    


}
 
Zuletzt bearbeitet:

Shams

Aktives Mitglied
Ich habe nun zwei Klassen, wie folgt (vielen Dank an Admiral Helmut, ich denke, dass das, was ich in der Zwischenzeit gemacht habe, dasselbe is :)):

Java:
import java.io.*;

public class Main implements Runnable//implements Runnable
{
	TestClass tc;
	public Main(TestClass t){
		super();
		tc=t;
		
		
	}

	@Override
	public void run() {		
		tc.increment();
	  }
 
	
	public static void main(String[] args) 
	{
		TestClass tc = new TestClass();
		
		Main m = new Main(tc);

		Thread t1 = new Thread(m);
		Thread t2 = new Thread(m);
		t1.start();
		t2.start();

    }	 
}

und

Java:
public class TestClass {

public int count = 0; //Ob dies static ist, ist für synchronized egal.
	
	public int getCount() {
		return count;
	}

	public void setCount(int z){
		count=z;
	}
	 
	public synchronized void increment(){
		
		while(count<66){
		
        int zahl = getCount();
         zahl++;
        setCount(zahl);
         System.out.println(zahl);
     
		} 
		
	}
	
}


...ich habe es jetzt auch mal laufen lassen, und es werden die Zahlen von 1-66 ausgegeben.
 
Zuletzt bearbeitet:

Admiral Helmut

Aktives Mitglied
Das sieht vom Aufbau schon gut aus, die Synchronisierung in EIN Datenobject verlagert. Damit ist es Threadsafe.

Erklär mir und dir ;) bitte den SInn der While schleife in deinem Programm.

dein erster Thread geht in die Synchronised Methode und sperrt sie.
dann geht er in die While Schleife. incrementiert 1, dann 2 ... er bleibt solange in der while schleife bist er bei 66 ist.

Achtung Methode immernoch gesperrt.

jetzt geht er aus der while schleife raus und gibt die Methode frei.
Jetzt darf Thread 2 zum ersten Mal in die Methode.
Thread 2:"Ohhh Count ist ja schon 66. Dann geh ich gar nicht in die While schleife". Programm Ende.

Nur Thread 1 gibt die Zahlen 1-66 aus

Ich denke da du dich mit Threads beschäftigst willst du abwechselnd incrementieren.

Ersetze deine While schleife mal durch eine if() Abfrage


Java:
if(count<66){
...increment....

}


Gruß Helmut
 
Zuletzt bearbeitet:

Bug Fisher

Bekanntes Mitglied
Am Ende ist es egal, es war von Anfang an threadsafe !

Java:
public synchronized void foo() {/*code*/}
ist eine Abkürzung für
Java:
public void foo() {
     synchronized(this) {/*code*/}
}
Während
Java:
public static synchronized void foo() {/*code*/}
zu
Java:
public static void foo() {
     synchronized(<Klassenname>.class) {/*code*/}
}
wird.

Beide Varianten sind aber aus OO - Sicht ein Designfehler von Java und sollten vermieden werden, denn Synchronisationsvariablen sind auf die Art nicht privat zu machen.

Bsp.:

Java:
class Broken {
     public synchronized void method() {}
}

class UserOfBroken {
     Broken b = new Broken();

     void method() {
          synchronized(b) {/*pitfall*/}
     }
}

Das Szenario lässt sich analog für die static Variante bauen, da ist es ja sogar noch viel einfacher, ein
Java:
synchronized(Broken.class)
zu verbrechen.

Synchronisationsobjekte sollten private Member sein, ich nutze dabei meist das private Threadobjekt selbst, wenn es es gibt, ansonsten einfach ein
Java:
final Object monitor = new Object();
 

Shams

Aktives Mitglied
Dies ist dann eventuell die finale Version :)

Java:
public class TestClass {
 
public int count = 0;  



 
	public int getCount() {
		return count;
	}
 
	public void setCount(int z){
		count=z;
	}
 
	public synchronized void increment(){
 
 
        int zahl = getCount();
        
        zahl++;
        setCount(zahl);
        
           System.out.println(zahl);
 
 
	}
 
}


////////////////////////////////////////////////////////////

Java:
import java.io.*;
 
public class Main implements Runnable//implements Runnable
{
	TestClass tc;
	public Main(TestClass t){
		super();
		tc=t;
 
 
	}
 
	@Override
	public void run() {		
		tc.increment();
	  }
 
 
	public static void main(String[] args) 
	{
		TestClass tc = new TestClass();
 
		Main m = new Main(tc);
 
		
int x = 0;
while(x<20){
	
		Thread t1 = new Thread(m);
		Thread t2 = new Thread(m);

                t1.start();
		        t2.start();
x++;
}

//Ausgabe 1234567....
 
    }	 
}
 

Admiral Helmut

Aktives Mitglied
Hallo Bug Fisher,
kurze Frage an dich:
Ich verstehe deine Nachricht aber bist du dir sicher, dass es von anfang an threadsafe war:
Er synchronisiert ja eine ObjectMethode und macht nur den Counter static. Dadurch dürften doch mehrere Objekte zur gleichen Zeit zugreifen.
Das mit dem static synchronized (bzw über die Klasse eben) habe ich jetzt glaub ich verstanden. aber seine Methode ist oben ja nicht static

Gruß Helmut
 

Bug Fisher

Bekanntes Mitglied
Hallo Helmut, ja du hast recht, ich habe mich geirrt, sorry.
Habe nochmal genau hingesehen.

Jeder Thread nutzt im ersten Post dieses Threads einen anderen (Main.this) Monitor.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
frager2345 Thread - Methoden synchronized deklarieren Java Basics - Anfänger-Themen 10
berserkerdq2 Wo finde ich in der Java Api die Notation zu Threads bezüglich Synchronized? Java Basics - Anfänger-Themen 14
A Thread - Synchronized Java Basics - Anfänger-Themen 10
berserkerdq2 Findet eine parallele Verarbeitung in Java bei Threads erst statt, wenn man die Methoden auch synchronized? Und wie sieht bei Conditions aus? Java Basics - Anfänger-Themen 8
X Threads Zwei Threads, aber doppelte Ausgabe verhindern (synchronized) Java Basics - Anfänger-Themen 54
O synchronized Java Basics - Anfänger-Themen 39
O synchronized difference Java Basics - Anfänger-Themen 5
E Synchronisierte Methoden vs. Synchronized(lockObject) Block Java Basics - Anfänger-Themen 7
T Was bringt das synchronized bei der Methode? Java Basics - Anfänger-Themen 12
temi Synchronized(Monitor) Java Basics - Anfänger-Themen 2
Z Threads Threads - Zugriff auf Ressourcen ohne(Lock, Synchronized) Java Basics - Anfänger-Themen 2
V Parameter in synchronized-Blöcken verstehen Java Basics - Anfänger-Themen 2
M Threads synchronized und wait Java Basics - Anfänger-Themen 2
N Threads Probleme mit synchronized Java Basics - Anfänger-Themen 9
B synchronized threads Java Basics - Anfänger-Themen 17
J Threads Synchronized Java Basics - Anfänger-Themen 6
U synchronized / lock Java Basics - Anfänger-Themen 8
P Arraylist synchronized? Java Basics - Anfänger-Themen 6
X3TitanCore Methoden synchronized bei einer Methode Java Basics - Anfänger-Themen 2
P synchronized methoden Java Basics - Anfänger-Themen 3
B warum schließt synchronized andere threads nicht aus? Java Basics - Anfänger-Themen 7
M Synchronized klappt nicht Java Basics - Anfänger-Themen 11
E synchronized Methoden Java Basics - Anfänger-Themen 3
M synchronized( ref ) Java Basics - Anfänger-Themen 3
I Synchronized Threads Java Basics - Anfänger-Themen 4
R Problem: Threads Synchronized machen Java Basics - Anfänger-Themen 5
M OOP Synchronized Methoden, zugriff aus Threads Java Basics - Anfänger-Themen 4
X Threads und synchronized - Verständnisproblem Java Basics - Anfänger-Themen 3
M Kleines Problem mit Threads (synchronized) Java Basics - Anfänger-Themen 3
S Fragen zu synchronized + Singleton! Java Basics - Anfänger-Themen 10
S bin zu blöd für threads - wait, notify, synchronized Java Basics - Anfänger-Themen 11
J simple Frage zu synchronized Java Basics - Anfänger-Themen 4
S Threads: synchronized mach nicht was es soll? Java Basics - Anfänger-Themen 6
L Threads und synchronized Java Basics - Anfänger-Themen 8
R wait() in synchronized - Block oder nicht? Java Basics - Anfänger-Themen 4
X Synchronized Zugriff ArrayList<E> Java Basics - Anfänger-Themen 6
G synchronized Java Basics - Anfänger-Themen 5
M synchronized variables? Java Basics - Anfänger-Themen 8
B Verständnissfrage synchronized Java Basics - Anfänger-Themen 2
S Warum wirkt hier synchronized nicht? Java Basics - Anfänger-Themen 9
C Trotz "synchronized" unerwartete Ausgabe Java Basics - Anfänger-Themen 2
E Synchronized - Methoden in verschied. Klassen Java Basics - Anfänger-Themen 3
C synchronized Java Basics - Anfänger-Themen 2
J Fragen zu Synchronized Java Basics - Anfänger-Themen 6
T synchronized HashMap Java Basics - Anfänger-Themen 7
L Problem mit synchronized und String Java Basics - Anfänger-Themen 2
A Problem mit Threads und synchronized Java Basics - Anfänger-Themen 3
B Was bedeutet synchronized? Java Basics - Anfänger-Themen 8
T Schlüsselworte Schlüsselwort this im Konstruktor Java Basics - Anfänger-Themen 3
J doppelname nach schlüsselwort extends Java Basics - Anfänger-Themen 4
V Was bewirkt das Schlüsselwort extends in Verbindung mit class bzw. public class ? Java Basics - Anfänger-Themen 2
R Erste Schritte Schlüsselwort "this" Java Basics - Anfänger-Themen 7
T Compiler-Fehler Methode ist Abstrakt obwohl kein Schlüsselwort gesetzt wurde Java Basics - Anfänger-Themen 5
B Warum wird String im Code nicht als Schlüsselwort markiert? Java Basics - Anfänger-Themen 11
B Methoden toString Methode mit Schlüsselwort new Java Basics - Anfänger-Themen 3
B Schlüsselwort new Java Basics - Anfänger-Themen 1
H Mehrfachdeklaration und das const-Schlüsselwort Java Basics - Anfänger-Themen 7
X Stringinhalt bis zu einem Schlüsselwort löschen Java Basics - Anfänger-Themen 6
M Der Java Schlüsselwort null; ?Welche Anweisung und Sinn? Java Basics - Anfänger-Themen 12
V Das Schlüsselwort "new" unter Java! Java Basics - Anfänger-Themen 2
J schlüsselwort static Java Basics - Anfänger-Themen 9
M Inkrementierung und Dekrementierung Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben