Synchronous static methods
Synchronized can also be applied to static methods, and if so, it represents the class lock that corresponds to the current. java file . Take a look at the example and note that PRINTC () is not a static method:
Public classthreaddomain25{ Public synchronized Static voidPrintA () {Try{System.out.println ("Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Enter Printa () method"); Thread.Sleep (3000); System.out.println ("Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Leave Printa () method"); } Catch(interruptedexception e) {e.printstacktrace (); } } Public synchronized Static voidPrintb () {System.out.println ("Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Enter Printb () method"); System.out.println ("Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Leave Printb () method"); } Public synchronized voidPrintc () {System.out.println ("Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Enter PRINTC () method"); System.out.println ( "Thread Name:" + Thread.CurrentThread (). GetName () + "in" + system.currenttimemillis () + "Leave Printc () method"); }}
Write three threads to invoke these three methods individually:
Public class extends thread{ publicvoid run () { threaddomain25.printa ();} }
public class mythread25_1 extends thread{ public void run () {THREADDOMAIN25.PRINTB (); }}
Public class extends thread{ Private ThreadDomain25 td; Public Mythread25_2 (ThreadDomain25 TD) { this. td = TD; } Public void Run () { td.printc (); }}
Write a main function to start the three threads:
Public Static void Main (string[] args) { new ThreadDomain25 (); New mythread25_0 (); New Mythread25_1 (); New Mythread25_2 (TD); Mt0.start (); Mt1.start (); Mt2.start ();}
Look at the results of the operation:
The thread name is: thread-0 in 1443857019710 Enter Printa () method thread name is:thread2 in 1443857019710 enter PRINTC () method thread name is: Thread -2 in 1443857019710 leave Printc () method thread name is:thread-0 in 1443857022710 leave Printa () method thread name is: Thread- 1 in 1443857022710 Enter PRINTB () method thread name is: Thread1 in 1443857022710 leave Printb () method
From the result of the run, the call to the PRINTC () method and the call to the Printa () method, the Printb () method are asynchronous, which shows that the static synchronous method and the non-static synchronization method hold different locks, the former is a class lock, and the latter is an object lock .
The so-called class lock, to give a further concrete example. If a class has a static synchronization method a,new out two classes of instance B and instance C, thread D holds instance B, thread E holds instance C, and as long as thread D calls the A method, then thread E calls the A method must wait for thread D to finish executing the A method, although two threads hold different objects.
volatile keyword
Give an example straight ahead:
Public classMyThread28extendsthread{Private BooleanIsRunning =true; Public Booleanisrunning () {returnisrunning; } Public voidSetrunning (Booleanisrunning) { This. isrunning =isrunning; } Public voidrun () {System.out.println ("Into run."); while(IsRunning = =true) {} System.out.println ("The thread is stopped."); }}
Public Static void Main (string[] args) { try { new MyThread28 (); Mt.start (); Thread.Sleep (+); Mt.setrunning (false); SYSTEM.OUT.PRINTLN ("Assigned to false"); } Catch (interruptedexception e) { e.printstacktrace (); }}
Look at the results of the operation:
Entered run, assigned to False
Perhaps the result is a bit strange, obviously isrunning has been set to false, the thread has not stopped it?
This is going to start with the Java memory Model (JMM), where the virtual machine will be described in detail. Depending on the main memory in the Jmm,java, different threads have their own working memory, and the same variable value has one copy in main memory, and if the thread uses this variable, it has an identical copy in its working memory. Each time the thread enters the variable value from main memory, the thread synchronizes the variable from the working memory back into main memory each time it executes.
Printing results occur because of a different step in the main memory and in the working memory. Because the run () method is executed with a copy of the main memory isrunning, and the setup isrunning is done in the main function, in other words, the isrunning setting is the isrunning in main memory, and the isrunning of the main memory is updated , the isrunning in the thread's working memory is not updated, and of course it has been looped, because for the thread, its isrunning is still true.
Solving this problem is simple, add volatile to the IsRunning keyword. Adding volatile means that each time the value of isrunning is read, the isrunning is synchronized from the main memory to the working memory of the thread, and then the current time is the latest isrunning. Take a look at the run effect of the volatile keyword for isrunning:
Entered run, the assigned value is False, the thread is stopped.
See this thread stopped because the most recent isrunning value was read from main memory, the isrunning in the thread's working memory became false, and the natural while loop ended.
This is the effect of volatile, a variable modified by volatile, to ensure that each read is the most recent value. Thread safety revolves around the two characteristics of visibility and atomicity , andvolatile addresses the visibility of variables across multiple threads, but does not guarantee security .
Synchronized, in addition to the protection of atomicity, in fact, but also to ensure the visibility of. Because synchronized either synchronous or synchronized blocks of code, the primary memory data is copied into the working memory, the synchronization block ends, and the data in the working memory is updated to main memory so that the data in the main memory must be up-to-date.
There is no guarantee of thread safety for atomic classes
Atomic operations indicate that an operation is indivisible, and no other thread can break or check for variables that are in an atomic operation. An atomic class is a class that can be used by an atomic operation, which guarantees thread safety without a lock.
But this thread safety is not absolute, and in the case of logic the output is also random, such as
public class threaddomain29{ public static Atomicinteger airef = new Atomicinteger (); public void Addnum () {System.out.println (Thread.CurrentThread (). GetName () + "result after 100:" + Airef.addandget ( 100 1); }}
Public class extends thread{ Private ThreadDomain29 td; Public MyThread29 (ThreadDomain29 TD) { this. td = TD; } Public void Run () { td.addnum (); }}
Public Static voidMain (string[] args) {Try{ThreadDomain29 TD=NewThreadDomain29 (); Mythread29[] MT=NewMythread29[5]; for(inti = 0; i < mt.length; i++) {Mt[i]=NewMyThread29 (TD); } for(inti = 0; i < mt.length; i++) {Mt[i].start (); } thread.sleep (1000); System.out.println (ThreadDomain29.aiRef.get ()); } Catch(interruptedexception e) {e.printstacktrace (); }}
Here's an integer atomic class Atomicinteger to see the results:
The result of the Thread-1 100: The resultof a 4 plus 100: The result of a 3plus 100: Results after 2 plus 100:100505Thread-0 added 100 results.
Obviously, the result is correct, but not what we want, because we definitely want the output to be added in order, and now it's 200, 500, 400, 300, 100. The cause of this problem is that both airef.addandget (100) and Aairef.addandget (1) are divisible.
The solution is to add synchronized to the Addnum method.
Java multithreading 6:synchronized locking class methods, volatile keywords, and other