Die grundlegendste Synchronisierungsmethode in Java besteht darin, das synchronisierte Schlüsselwort zu verwenden, um den gleichzeitigen Zugriff auf eine Methode zu steuern. Jede mit dem synchronisierten Schlüsselwort deklarierte Methode ist ein kritischer Abschnitt. In Java darf nur auf einen kritischen Abschnitt desselben Objekts gleichzeitig zugegriffen werden.
Statische Methoden haben ein unterschiedliches Verhalten. Auf statische Methoden, die mit dem synchronisierten Schlüsselwort deklariert werden, kann nur ein Ausführungsthread gleichzeitig zugreifen, andere Threads können jedoch auf die nicht statischen synchronisierten Methoden dieses Objekts zugreifen. Dabei müssen Sie sehr vorsichtig sein, da zwei Threads gleichzeitig auf zwei verschiedene synchronisierte Methoden eines Objekts zugreifen können, d. h. eine davon ist eine statische synchronisierte Methode und die andere eine nicht statische synchronisierte Methode. Wenn beide Methoden dieselben Daten ändern, tritt ein Dateninkonsistenzfehler auf. Die Syntax von
synchronized block lautet wie folgt:
public void method() { synchronized(表达式) { } }
Das synchronisierte Schlüsselwort hat zwei Verwendungszwecke, eines wird nur in der Definition von Methoden verwendet und das andere ist synchronisierter Block Nicht nur Können wir „synchonized“ verwenden, um eine Objektvariable zu synchronisieren? Sie können „synchonizeddl“ auch verwenden, um statische und nicht statische Methoden in einer Klasse zu synchronisieren.
Das erste: Synchronisierung nicht statischer Methoden
Aus der relevanten Java-Syntax können wir erkennen, dass die Verwendung des synchronisierten Schlüsselworts zum Definieren von Methoden die definierten statischen Methoden und nicht statischen Methoden sperrt Verwenden Sie das Schlüsselwort synchroniezd in der Klasse. Dies ist jedoch etwas schwierig zu verstehen. Wenn Sie möchten, dass ein synchronisierter Block einen solchen Effekt erzielt, ist es nicht schwer zu verstehen, warum dieser Effekt auftritt Synchronisierte nicht statische Methoden in der Klasse müssen Sie nur verwenden. Dies wird als Parameter des synchronisierten Blocks an den synchronisierten Block übergeben. Der Code lautet wie folgt:
public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } } public class Test { public void method1() { synchronized(this) { } } public synchronized void method2() { } }
Im obigen Code Methode1 verwendet den synchronisierten Block, und die Methode method2 verwendet das synchronisierte Schlüsselwort, um die Methode zu definieren. Wenn Sie dieselbe Testinstanz verwenden, werden die anderen Methoden blockiert, da sie nicht abgerufen werden, solange eine dieser beiden Methoden ausgeführt wird die Synchronisationssperre. Zusätzlich zur Verwendung als Parameter des synchronisierten Blocks können Sie Test.this auch als Parameter des synchronisierten Blocks verwenden, um den gleichen Effekt zu erzielen.
In synchronisierten Blöcken, die in inneren Klassen verwendet werden, stellt dies nur die innere Klasse dar und hat nichts mit der äußeren Klasse (OuterClass) zu tun. Aber auch nicht statische Methoden in der inneren Klasse und nicht statische Methoden in der äußeren Klasse können synchronisiert werden. Wenn Sie der inneren Klasse eine Methode method3 hinzufügen, können Sie diese auch mit den beiden Methoden in Test synchronisieren. Der Code lautet wie folgt:
public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } } public class Test { class InnerClass { public void method3() { synchronized(Test.this){ } } } }
Die obige Methode method3 von InnerClass und die Methoden method1 und method2 Der Test kann nur gleichzeitig synchronisiert werden. Es kann eine Möglichkeit geben, dies zu tun.
Unabhängig davon, ob der synchronisierte Block korrekt ausgeführt wird oder aufgrund einer Ausnahme aufgrund eines Programmfehlers den synchronisierten Block verlässt, wird die vom aktuellen synchronisierten Block gehaltene Synchronisationssperre automatisch aufgehoben, sodass Sie sich keine Sorgen um die Synchronisationssperre machen müssen Problem bei Verwendung des synchronisierten Blocks.
2. Synchronisierung statischer Methoden
Da die Objektinstanz beim Aufrufen der statischen Methode nicht unbedingt erstellt wird, können Sie diese nicht zum Synchronisieren der statischen Methode verwenden, sondern müssen zum Synchronisieren das Klassenobjekt verwenden die statische Methode. Der Code lautet wie folgt:
public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } } public class Test{ pubic static void method1(){ synchronized(Test.class){ } } public static synchronized void method2(){ } }
Beim Synchronisieren statischer Methoden können Sie die statische Feldklasse der Klasse verwenden, um das Klassenobjekt abzurufen. Im obigen Beispiel haben die Methoden method1 und method2 nur eine Methode ausführen. Zusätzlich zur Verwendung des Klassenfelds können Sie das Klassenobjekt auch über die getClass()-Methode der Instanz abrufen Im obigen Code erhalten wir eine Testinstanz über ein öffentliches statisches Objekt und übergeben die getClass-Methode der Instanz, um ein Klassenobjekt abzurufen (beachten Sie, dass alle Instanzen einer Klasse dasselbe Klassenobjekt über die getClass-Methode erhalten). Wir können auch statische Methoden verschiedener Klassen über die Klasse synchronisieren. Der Code lautet wie folgt:
public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } } public class Test{ public static Test test; public Test(){ test=this; } public static void method1(){ synchronized(test.getClass()){ } } }
Hinweis: Wenn Sie synchronisierte Blöcke zum Synchronisieren von Methoden verwenden, können nicht statische Methoden dadurch synchronisiert werden, während statische Methoden verwendet werden Zum Synchronisieren muss ein Klassenobjekt verwendet werden. Nicht statische Methoden können jedoch auch statische Methoden mithilfe der Klasse synchronisieren. Dies kann jedoch in statischen Methoden nicht zum Synchronisieren nicht statischer Methoden verwendet werden. Dies ist bei der Verwendung synchronisierter Bausteine zu beachten.
public class Test1{ public static void method1(){ synchronized(Test.class){ } } } public class Test1{ public static void method1(){ synchronized(Test.class){ } } }
Das synchronisierte Schlüsselwort verringert die Leistung der Anwendung, sodass es nur in gleichzeitigen Szenarien für Methoden verwendet werden kann, die gemeinsam genutzte Daten ändern müssen. Wenn mehrere Threads auf dieselbe synchronisierte Methode zugreifen, kann nur ein Thread darauf zugreifen und die anderen Threads warten. Wenn die Methodendeklaration nicht das synchronisierte Schlüsselwort verwendet, können alle Threads die Methode gleichzeitig ausführen, wodurch sich die Gesamtlaufzeit verringert. Wenn bekannt ist, dass eine Methode nicht von mehr als einem Thread aufgerufen wird, ist es nicht erforderlich, sie mit dem synchronisierten Schlüsselwort zu deklarieren.
Als synchronisiert deklarierte Methoden können rekursiv aufgerufen werden. Wenn ein Thread auf die synchronisierte Methode eines Objekts zugreift, kann er auch andere synchronisierte Methoden des Objekts aufrufen, einschließlich der gerade ausgeführten Methode, ohne erneut Zugriff auf diese Methode erhalten zu müssen.
我们可以通过synchronized关键字来保护代码块(而不是整个方法)的访问。应该这样利用synchronized关键字:方法的其余部分保持在synchronized代码块之外,以获取更好的性能。临界区(即同一时间只能被一个线程访问的代码块)的访问应该尽可能的短。例如在获取一幢楼人数的操作中,我们只使用synchronized关键字来保护对人数更新的指令,并让其他操作不使用共享数据。当这样使用synchronized关键字时,必须把对象引用作为传入参数。同一时间只有一个线程被允许访问这个synchronized代码。通常来说,我们使用this关键字来引用正在执行的方法所属的对象:
synchronized(this){ //Java code }
更多Java中synchronized关键字修饰方法同步的用法详解相关文章请关注PHP中文网!