suchen
HeimJavajavaLernprogrammVerwendung des synchronisierten Schlüsselworts

Das synchronisierte Schlüsselwort ist eine Synchronisationssperre, die häufig in der gleichzeitigen Java-Programmierung verwendet wird. Es wird zum Sperren von Methoden oder Codeblöcken verwendet und kann synchronisiert (dieses) {}, synchronisiert (Objekt) {} sein (Klasse) {}.

Verwendung des synchronisierten Schlüsselworts

Die Sperre wird automatisch aufgehoben, wenn der gesperrte Inhalt ausgeführt wird oder während der Ausführung eine Ausnahme ausgelöst wird.

Wenn Sie die Sperre manuell aufheben möchten, müssen Sie die Methode wait() des gesperrten Objekts aufrufen, um die Sperre aufzuheben und in einen Wartezustand zu versetzen, zu anderen Threads zur Ausführung wechseln und benachrichtigen Die ()-Methode weckt nur das aufgerufene Objekt der wait()-Methode anderer Threads, die Sperre wird jedoch nicht aufgehoben, und die Auswahlreihenfolge wird nicht durch den Code gesteuert, sondern von der virtuellen Maschine implementiert.

Daher können die Methoden wait(), notify() und notifyAll() des Objekts nur mit dem synchronisierten Schlüsselwort verwendet werden, um die Planung zwischen Threads abzuschließen.

wobei die gesperrte Methode äquivalent zu synchronisiert(this){all code of the method as a code block} ist, wie folgt:

public synchronized void test() {
...
}

ist äquivalent zu

public void test() {
synchronized (this) {
...
}
}

gesperrt Im obigen Beispiel handelt es sich um ein Objekt dieser Klasse. Wir wissen, dass die statische Methode zur Klasse und nicht zum Objekt gehört. Daher sperrt die durch die Synchronisierung geänderte statische Methode alle Objekte dieser Klasse Das heißt, auch zwei Instanzobjekte werden gesperrt, solange sie dieser Klasse angehören.

public synchronized static void test() {
	...
}

entspricht

public static void test() {
synchronized (所在类.class) {
...
}	
}

Ob es sich um eine Sperrmethode oder einen Codeblock handelt, unabhängig vom Referenzobjekt beim Sperren des Codeblocks ist es klar, solange Sie sich an eines erinnern Prinzip, das heißt, wenn das Referenzobjekt synchronisiert ist, funktionieren Sperren nur, wenn sie gleich sind. Andernfalls schließen sich die Sperren nicht gegenseitig aus und können gleichzeitig ausgeführt werden.

synchronized(this) zeigt an, dass die Sperre wirksam wird, wenn die Objektinstanzen der aktuellen Klasse gleich sind, synchronisiert(Object) zeigt an, dass die Sperre wirksam wird, wenn die Objektobjekte gleich sind, und synchronisiert(class ) zeigt an, dass die Sperre wirksam wird, wenn alle derselben Klasse angehören.

Geben Sie ein einfaches Beispiel:

public class TestController {
 
    public class Task implements Runnable{
		private String str;
		
		Task(String str){
			this.str=str;
		}
		
		@Override
		public void run() {
			synchronized (str) {
				try {
					Thread.sleep(3000l);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println(str);
			}
		}
		
	}
	
	public static void main(String[] args) throws InterruptedException {
		TestController testController = new TestController();
		Thread thread1 = new Thread(testController.new Task("1"));
		Thread thread2 = new Thread(testController.new Task("1"));
		thread1.start();
		thread2.start();
	}
}

Im obigen Code ist das Referenzobjekt str alles „1“. In Java, wenn die Zeichenfolge this.str="1" übergibt, Zuweisung entspricht str=String.valueOf("1"). Wenn die Zeichenfolge "1" zuvor initialisiert wurde, wird die vorherige direkt übernommen, es handelt sich also um dasselbe Objekt. Gemäß dem oben eingeführten Prinzip wird die Sperre wirksam, sodass nach 3 Sekunden 1 und nach weiteren 3 Sekunden 1 ausgegeben wird.

Wenn Thread2 in

Thread thread2 = new Thread(testController.new Task("2"));

geändert wird, ist eines der Referenzobjekte „1“ und das andere „2“, die nicht dasselbe Objekt sind, sodass die Sperre nicht gegenseitig erfolgt exklusiv funktioniert, das Ergebnis ist, dass 1 und 2 nach 3 Sekunden fast gleichzeitig ausgegeben werden.

Bei all dem handelt es sich um mehrere Threads, die gleichzeitig dieselbe Methode aufrufen. Was ist, wenn verschiedene Methoden aufgerufen werden?

public class Test{
	
	public synchronized void m1(){
		System.out.println("m1 running...");
		try {
			Thread.sleep(3000l);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("m1 end");
	}
	
	public synchronized void m2(){
		System.out.println("m2 running...");
		System.out.println("m2 end");
	}
	
	public static void main(String[] args) {
		Test test = new Test();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.m1();
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				test.m2();
			}
		}).start();
	}
	
}

Das Ausgabeergebnis des obigen Codes ist:

m1 running...
//过3秒
m1 end
m2 running...
m2 end

Wie oben erwähnt, entspricht die synchronisierte Änderung synchronisiert(this) {dem gesamten Code der Methode als Codeblock} und Dies stellt ein Objekt dar, das heißt, der erste Thread erhält die Sperre des Testobjekts. Da alle Objekte gleich sind, kann der zweite Thread die Sperre nicht erhalten und ist blockiert.

Ändern Sie das obige Beispiel wie folgt:

private String str = "1";
	
public void m1(){
	synchronized(str){
		System.out.println("m1 running...");
		try {
			Thread.sleep(3000l);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("m1 end");
	}
}
 
public void m2(){
	synchronized(str){
		System.out.println("m2 running...");
		System.out.println("m2 end");
	}
}

Wenn der erste Thread m1() aufruft, erhält er die Sperre des Objekts str. Der zweite Thread benötigt sie auch, wenn er m2( ). Erhalten Sie die Sperre des Objekts str. Da es sich um dasselbe Testobjekt handelt, sind die beiden Stränge auch dasselbe Objekt, sodass der zweite Thread blockiert wird, da er die Sperre nicht erhalten kann und das Ausgabeergebnis dasselbe ist wie das vorherige Beispiel.

Wenn Sie das obige Beispiel wie folgt ändern:

public class M1 {
	
	public void m(String str){
		synchronized (str) {
			System.out.println("m1 runing");
			try {
				Thread.sleep(3000l);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("m1 end");
		}
	}
 
}
public class M2 {
	
	public void m(String str){
		synchronized (str) {
			System.out.println("m2 runing");
			System.out.println("m2 end");
		}
	}
 
}
public class Test {
 
	public static void main(String[] args) {
		String str = "1";
		new Thread(new Runnable() {
			@Override
			public void run() {
				new M1().m(str);
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				new M2().m(str);
			}
		}).start();
	}
	
}

Die dieses Mal aufgerufene Methode ist in zwei Klassen, aber das Ergebnis ist das gleiche wie in den beiden vorherigen Beispielen, da sie gesperrt sind Alle übergebenen str-Objekte. Es gibt nur eine Sperre für dasselbe Objekt. Wenn der erste Thread sie übernimmt, kann der zweite Thread nur warten.

Zusammenfassung:

A. Unabhängig davon, ob das synchronisierte Schlüsselwort einer Methode oder einem Objekt hinzugefügt wird, gilt die Sperre, wenn das Objekt, auf das es wirkt, nicht statisch ist Es erhält das Objekt. Wenn das Objekt, auf das synchronisiert wird, eine statische Methode oder eine Klasse ist, gilt die Sperre, die es erhält, für die Klasse, und alle Objekte der Klasse haben dieselbe Sperre.

B. Jedem Objekt ist nur eine Sperre zugeordnet. Wer diese Sperre erhält, kann den von ihm gesteuerten Code ausführen.

C. Die Implementierung der Synchronisierung erfordert einen hohen Systemaufwand und kann sogar zu einem Deadlock führen. Vermeiden Sie daher unnötige Synchronisierungskontrollen

Das obige ist der detaillierte Inhalt vonVerwendung des synchronisierten Schlüsselworts. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme
Dieser Artikel ist reproduziert unter:CSDN. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen
Wie benutze ich Maven oder Gradle für das fortschrittliche Java -Projektmanagement, die Erstellung von Automatisierung und Abhängigkeitslösung?Wie benutze ich Maven oder Gradle für das fortschrittliche Java -Projektmanagement, die Erstellung von Automatisierung und Abhängigkeitslösung?Mar 17, 2025 pm 05:46 PM

In dem Artikel werden Maven und Gradle für Java -Projektmanagement, Aufbau von Automatisierung und Abhängigkeitslösung erörtert, die ihre Ansätze und Optimierungsstrategien vergleichen.

Wie erstelle und verwende ich benutzerdefinierte Java -Bibliotheken (JAR -Dateien) mit ordnungsgemäßem Versioning und Abhängigkeitsmanagement?Wie erstelle und verwende ich benutzerdefinierte Java -Bibliotheken (JAR -Dateien) mit ordnungsgemäßem Versioning und Abhängigkeitsmanagement?Mar 17, 2025 pm 05:45 PM

In dem Artikel werden benutzerdefinierte Java -Bibliotheken (JAR -Dateien) mit ordnungsgemäßem Versioning- und Abhängigkeitsmanagement erstellt und verwendet, wobei Tools wie Maven und Gradle verwendet werden.

Wie implementiere ich mehrstufige Caching in Java-Anwendungen mit Bibliotheken wie Koffein oder Guava-Cache?Wie implementiere ich mehrstufige Caching in Java-Anwendungen mit Bibliotheken wie Koffein oder Guava-Cache?Mar 17, 2025 pm 05:44 PM

In dem Artikel wird in der Implementierung von mehrstufigem Caching in Java mithilfe von Koffein- und Guava-Cache zur Verbesserung der Anwendungsleistung erläutert. Es deckt die Einrichtungs-, Integrations- und Leistungsvorteile sowie die Bestrafung des Konfigurations- und Räumungsrichtlinienmanagements ab

Wie kann ich JPA (Java Persistence-API) für Objektrelationszuordnungen mit erweiterten Funktionen wie Caching und faulen Laden verwenden?Wie kann ich JPA (Java Persistence-API) für Objektrelationszuordnungen mit erweiterten Funktionen wie Caching und faulen Laden verwenden?Mar 17, 2025 pm 05:43 PM

In dem Artikel werden mit JPA für Objektrelationszuordnungen mit erweiterten Funktionen wie Caching und faulen Laden erläutert. Es deckt Setup, Entity -Mapping und Best Practices zur Optimierung der Leistung ab und hebt potenzielle Fallstricke hervor. [159 Charaktere]

Wie funktioniert der Klassenladungsmechanismus von Java, einschließlich verschiedener Klassenloader und deren Delegationsmodelle?Wie funktioniert der Klassenladungsmechanismus von Java, einschließlich verschiedener Klassenloader und deren Delegationsmodelle?Mar 17, 2025 pm 05:35 PM

Mit der Klassenbelastung von Java wird das Laden, Verknüpfen und Initialisieren von Klassen mithilfe eines hierarchischen Systems mit Bootstrap-, Erweiterungs- und Anwendungsklassenloadern umfasst. Das übergeordnete Delegationsmodell stellt sicher

See all articles

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vorBy尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Herunterladen der Mac-Version des Atom-Editors

Herunterladen der Mac-Version des Atom-Editors

Der beliebteste Open-Source-Editor

PHPStorm Mac-Version

PHPStorm Mac-Version

Das neueste (2018.2.1) professionelle, integrierte PHP-Entwicklungstool

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

WebStorm-Mac-Version

WebStorm-Mac-Version

Nützliche JavaScript-Entwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)