Traditional threads are mutually exclusive and synchronous, while traditional threads are mutually exclusive.
The traditional thread mutex and synchronous communication are implemented through the synchronized keyword and wait () and notify () methods.
First, we will introduce the synchronized keyword.
The synchronized keyword, which has two usage methods: synchronized Method and synchronized block.
1. synchronized Method: declare the synchronized Method by adding the synchronized keyword to the method declaration. For example:
public synchronized void accessVal(int newVal);
The synchronized method controls access to class member variables: each class instance corresponds to a lock, and each synchronized method must obtain the lock of the class instance that calls the method before execution, otherwise the thread is blocked, once the method is executed, the lock is exclusive until the lock is released when the method is returned. Then, the blocked thread can obtain the lock and re-enter the executable status. This mechanism ensures that, at the same time, only one of all the member functions declared as synchronized is in the executable state (because at most only one member function can obtain the lock corresponding to this type of instance ), this effectively avoids access conflicts between class member variables (as long as all methods that may be used to invoke class member variables are declared as synchronized ).
In Java, not only are class instances, but each class also corresponds to a lock. In this way, we can declare the static member function of the class as synchronized, to control its access to static member variables of the class. Synchronized: if a large method is declared as synchronized, the efficiency will be greatly affected. Typically, if you declare the thread-class method run () as synchronized, since the thread is always running throughout its life cycle, it will never succeed in calling any synchronized Method of this class. Of course, we can put the code of the member variable of the category class into a special method, declare it as synchronized, and call it in the main method to solve this problem, but Java provides us with a better solution, that is, the synchronized block.
2. synchronized block: Use the synchronized keyword to declare the synchronized block. Syntax:
1 synchronized (syncObject) {2 // code 3 that allows access control}
The synchronized block is a code block in which the Code must obtain the lock of the object syncObject (as described earlier, it can be a class instance or class) before execution. The specific mechanism is described earlier. It is highly flexible because it can target any code block and can specify any locked object.
Note: Using synchronized blocks in Java can reduce the lock time on resources and improve system performance. The syncronized-locked object must be the same object. Otherwise, the effect of mutual exclusion cannot be achieved. For the mutex of the static method, the bytecode object of the class to be locked, that is, the class name. class.
Example:
1 public class TraditionalSynchronized {2 public static void main (String [] args) {3 final Outputer outputer = new Outputer (); 4 new Thread (new Runnable () {5 @ Override 6 public void run () {7 while (true) {8 outputer. outputer ("love"); 9} 10} 11 }). start (); 12 new Thread (new Runnable () {13 @ Override14 public void run () {15 while (true) {16 Outputer. outputer3 ("hite"); 17} 18} 19 }). start (); 20 21} 22} 23 // print String 24 class Outputer {25 public void outputer (String name) {26 int len = name. length (); 27 synchronized (Outputer. class) {28 for (int I = 0; I <len; I ++) {29 System. out. print (name. charAt (I); 30} 31 System. out. println (); 32} 33 34} 35 public synchronized void outputer2 (String name) {36 int len = name. length (); 37 for (int I = 0; I <len; I ++) {38 System. out. print (name. charAt (I); 39} 40 System. out. println (); 41} 42 public static synchronized void outputer3 (String name) {43 int len = name. length (); 44 for (int I = 0; I <len; I ++) {45 System. out. print (name. charAt (I); 46} 47 System. out. println (); 48} 49}
Synchronous thread communication is implemented through the wait () and notify () Methods of the Object. Wait (): The current thread must have this object monitor. This thread releases ownership of this monitor and waits until other threads pass the callnotifyMethod, ornotifyAllMethod to notify the waiting thread to wake up on the monitor of this object. Then the thread will not continue execution until it obtains ownership of the monitor again. Y (): Wake up a single thread waiting on this object monitor. If all threads are waiting on this object, the system will wake up one of the threads. The choice is arbitrary and occurs when a decision is made on the implementation. The thread calls one ofwaitMethod, waiting on the object's monitor.
Now we use the following code to implement a subthread loop for 10 times, the main thread loops for 100 times, the subthread loops for 10 times again, and the main thread loops for 100 times again. So reciprocating 50 times. This example combines thread mutex with thread communication to deepen the impression.
1 public class TraditionalCommunication {2 public static void main (String [] args) {3 final Business business = new Business (); 4 new Thread (new Runnable () {5 @ Override 6 public void run () {7 for (int I = 0; I <50; I ++) {8 business. sub (I); 9} 10} 11 }). start (); 12 new Thread (new Runnable () {13 @ Override14 public void run () {15 for (int I = 0; I <50; I ++) {16 business. main (I); 17} 18} 19 }). star T (); 20} 21} 22 23/** 24 * to solve the multithreading problem, try to put the thread in the class for internal solution instead of synchronizing in multiple threads, this simplifies the program 25 * @ author luchao26 * 27 */28 class Business {29 private boolean isSubRun = true; 30 public synchronized void sub (int n) {31 while (! IsSubRun) {// if can be used here, but some programs have a "false Wakeup" status. Use while to add another judgment to avoid "false Wakeup" status 32 try {33 this. wait (); 34} catch (InterruptedException e) {35 e. printStackTrace (); 36} 37} 38 for (int I = 0; I <10; I ++) {39 System. out. println ("sub:" + I + "loop of:" + n); 40} 41 isSubRun = false; 42 this. Y (); // wake up main thread 43} 44 public synchronized void main (int n) {45 while (isSubRun) {46 try {47 this. wait (); 48} catch (InterruptedException e) {49 e. printStackTrace (); 50} 51} 52 for (int I = 0; I <100; I ++) {53 System. out. println ("main:" + I + "loop of:" + n); 54} 55 isSubRun = true; 56 this. Y (); // wake up sub-thread 57} 58}
Through the above example, we will summarize the following: in multi-threaded programming, we try to synchronize threads within the class, rather than synchronizing them through threads, which can simplify programming difficulty. In the synchronized method, a judgment is added through while () to increase the rigor of the program. This is because the thread can also wake up a so-called false wake-up without being notified, interrupted, or timed out.