Warum Fadensynchronisation
Denn wenn wir mehrere Threads haben, um gleichzeitig auf eine Variable oder ein Objekt zugreifen zu können, verursacht dies, wenn sowohl Lese- als auch Schreibvorgänge in diesen Threads vorhanden sind, Verwirrung im variablen Wert oder Objektstatus, was zu Ausnahmen von Programmausnahmen führt. Wenn beispielsweise ein Bankkonto gleichzeitig mit zwei Threads betrieben wird, wird einer 100 -Yuan -Abhebung abgehoben und der andere spart 100 Yuan. Angenommen, das Konto hatte ursprünglich 0 yuan, was würde passieren, wenn der Auszahlungs -Thread und der Spar -Thread gleichzeitig auftreten würden? Wenn die Auszahlung des Geldes nicht erfolgreich ist, beträgt der Kontostand 100. Wenn die Auszahlung des Geldes erfolgreich ist, beträgt der Kontostand 0. Also, welches ist das? Es ist schwer klar zu erklären. Daher soll die Synchronisation mit Multi-Threaden dieses Problem lösen.
1. Code, wenn er nicht synchron ist
Bank.java Package Threadtest; out .println (System.currentTimemillis ()+"Save:"+Money); ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::); void LookMoney () {System.out. (); {// todo auto -generiertes Block E. printstacktrace (); Thread (new Runnable () {@Override public void run () {// Todo automatisch generierte Methode Stub während (true) {bank.submoney (100); bank.lookmoney (); System.out.println ("/n "); try {thread.sleep (1000);} catch (interruptedException e) {// Todo automatisch generierter Block E. printstacktrace ();}}}}); tsub.start (); tad.start () ;}}
Der Code ist sehr einfach, ich werde es nicht erklären. Ich habe einige von ihnen abgefangen, ist es sehr chaotisch und ich kann das Schreiben nicht verstehen.
Unzureichender Guthabenkonto -Guthaben: 0
Unzureichender Guthabenkonto -Guthaben: 100
1441790503354 Kaution: 100
Kontostand: 100
1441790504354 Kaution: 100
Kontostand: 100
1441790504354 Take Out: 100
Kontostand: 100
1441790505355 Kaution: 100
Kontostand: 100
1441790505355 Take Out: 100
Kontostand: 100
2. Verwenden Sie den Synchroncode
(1) Synchronisationsmethode:
Es gibt eine Methode, um synchronisierte Schlüsselwörter zu ändern. Da jedes Objekt in Java über ein integriertes Schloss verfügt, schützt das integrierte Schloss die gesamte Methode, wenn die Methode mit diesem Schlüsselwort geändert wird. Bevor Sie diese Methode aufrufen, müssen Sie ein integriertes Schloss erhalten, da sie sich ansonsten in einem Blockierungszustand befindet.
Modifizierte Bank.java
Schauen wir uns die laufenden Ergebnisse an:
Unzureichender Guthabenkonto -Guthaben: 0
Unzureichender Guthabenkonto -Guthaben: 0
1441790837380SAVE: 100
Kontostand: 100
1441790838380 Take Out: 100
Kontosaldo: 0
1441790838380SAVE: 100
Kontostand: 100
1441790839381 entfernt: 100
Kontosaldo: 0
Ich habe das Gefühl, dass es sofort versteht.
Hinweis: Das synchronisierte Schlüsselwort kann auch statische Methoden ändern.
(2) Codeblöcke synchronisieren
Das heißt, es gibt einen Anweisungsblock, der durch synchronisiertes Schlüsselwort geändert wird. Der durch dieses Schlüsselwort geänderte Anweisungsblock wird automatisch mit einer integrierten Schloss hinzugefügt, um die Synchronisation zu erreichen
Bank.java Code lautet wie folgt:
Paket -ThreadTest;/** * @Author WW * */öffentliche Klasse Bank {private int count = 0; // Konto -Guthaben // Geldpublikum addmoney (int Money) {Synchronized (this) {count += Geld; System.out.println (System.currentTimemillis ()+"Save:"+Geld); .Println ("Unzureichende Balance"); {System.out.println ("Kontosaldo:"+count);
Die Betriebsergebnisse sind wie folgt:
Unzureichender Guthabenkonto -Guthaben: 0
1441791806699Saved: 100
Kontostand: 100
1441791806700 Take Out: 100
Kontosaldo: 0
1441791807699Saved: 100
Kontostand: 100
Der Effekt ähnelt der Methode.
HINWEIS: Die Synchronisation ist ein High-Overhead-Betrieb, sodass der synchronisierte Inhalt minimiert werden sollte. Normalerweise müssen die gesamte Methode nicht synchronisiert werden. Verwenden Sie einfach den synchronisierten Codeblock, um den Schlüsselcode zu synchronisieren.
(3) Verwenden Sie spezielle Domänenvariablen (volatil), um eine Gewindesynchronisation zu erreichen
A.Volatile Keyword bietet einen lock-freien Mechanismus für den Zugriff auf Domänenvariablen
b. Verwenden von volatilen, um die Domäne zu ändern, entspricht der virtuellen Maschine, dass die Domäne von anderen Threads aktualisiert werden kann.
c.
D.Volatile liefert weder atomare Operationen noch kann es verwendet werden, um Variablen des endgültigen Typs zu ändern
Bank.java Code lautet wie folgt:
Paket -ThreadTest; (System.CurrentTimillis () + "Save:" + Geld); ;} count -= Geld; " + count);}}
Wie ist der Betriebseffekt?
Unzureichender Guthabenkonto -Guthaben: 0
Unzureichender Guthabenkonto -Guthaben: 100
1441792010959Saved: 100
Kontostand: 100
1441792011960 Take Out: 100
Kontosaldo: 0
1441792011961Saved: 100
Kontostand: 100
Liegt es daran, dass ich es nicht wieder verstehen kann und es wieder unordentlich ist? Warum ist das? Es liegt daran, dass volatile Atomoperationen nicht garantieren können, sodass flüchtig die synchronisierte nicht ersetzen kann. Darüber hinaus organisiert volatile den Compiler, um den Code zu optimieren. Wenn Sie ihn also verwenden können, wird er nicht gelten. Sein Prinzip ist, dass jedes Mal, wenn ein Thread auf eine durch volatile modifizierte Variable zugreifen möchte. Er wird aus dem Speicher und nicht im Cache gelesen, sodass der von jedem Thread zugegriffene variable Wert gleich ist. Dies gewährleistet die Synchronisation.
(4) Verwenden Sie die Wiedereintrittsschloss, um die Threadsynchronisation zu erreichen
Javase5.0 wurde ein neues Java.util.Concurrent -Paket hinzugefügt, um die Synchronisation zu unterstützen. Die Wiedereintrittsklasse ist eine wiedereintretende, sich gegenseitig ausschließende Sperre, die die Sperrgrenze implementiert.
Häufige Methoden der ReenReantlock -Klasse sind:
Reentrantlock (): Erstellen Sie eine Re -Enterantlock -Instanz
lock (): das Schloss erhalten
Unlock (): Reentrantlock Hinweis: Reentrantlock () verfügt auch über einen Konstruktor, der faire Schlösser erstellen kann, es wird jedoch nicht empfohlen, ihn zu verwenden, da es die Ausführungseffizienz des Programms erheblich reduzieren kann.
Der Code von Bank.java wird wie folgt geändert:
Pakettest; //Sie müssen diese Sperre für private Lock -Lock = New ReentrantLock () sparen; TLN (System. if (count - Geld <0) {System.out.println ("Unzureichende Balance"); ;} endlich {lock.unlock ();
Wie ist der Betriebseffekt?
Unzureichender Guthabenkonto -Guthaben: 0
Unzureichender Guthabenkonto -Guthaben: 0
1441792891934 Einzahlung: 100
Kontostand: 100
1441792892935Saved: 100
Kontostand: 200
1441792892954 Take Out: 100
Kontostand: 100
Der Effekt ähnelt den ersten beiden Methoden.
Wenn das synchronisierte Schlüsselwort die Anforderungen der Benutzer erfüllen kann, verwenden Sie synchronisiert, da es den Code vereinfachen kann. Wenn Sie fortgeschrittene Funktionen benötigen, verwenden Sie zu diesem Zeitpunkt die REENTRANTS -Klasse.
(5) Verwenden Sie lokale Variablen, um die Threadsynchronisation zu erreichen
Bank.java Code lautet wie folgt:
Paket-Threadtest; / ** * @Author WW * * / öffentliche Klasse Bank {private statische ThreadLocal <Integer> count = new ThreadLocal <NeGeger> () {@Override p Drehete InitialValue () {// Todo Auto-Generated Method Stub Rückgabe 0; ); ()- Geld); zählen.
Laufeffekt:
Unzureichender Guthabenkonto -Guthaben: 0
Unzureichender Guthabenkonto -Guthaben: 0
1441794247939Saved: 100
Kontostand: 100
Unzureichendes Gleichgewicht
1441794248940Save: 100
Kontosaldo: 0
Kontostand: 200
Unzureichender Guthabenkonto -Guthaben: 0
1441794249941Saved: 100
Kontostand: 300
Nachdem ich den Betriebseffekt gesehen hatte, war ich am Anfang verwirrt. Schauen Sie sich das Prinzip von ThreadLocal an:
Wenn Sie ThreadLocal verwenden, um Variablen zu verwalten, wird jeder Thread mit der Variablen eine Kopie der Variablen erhalten, und die Kopien sind unabhängig voneinander, sodass jeder Thread seine eigene Kopie der Variablen nach Belieben ändern kann, ohne andere Threads zu beeinflussen. Jetzt verstehe ich. Der obige Effekt tritt also auf.
Threadlokal- und Synchronisationsmechanismus
A.Threadlocal- und Synchronisationsmechanismen sollen das Problem des Zugriffskonflikts derselben Variablen in Multithreads lösen
b.
Jetzt verstehe ich. Jeder hat seine eigenen Vor- und Nachteile und erhalte seine anwendbaren Szenarien.