1. Thread life cycle
1.1. Five states of threads
- Thread. Is used in JDK The state class defines several states of a thread
New: when a thread class or its subclass object is declared and created, the new thread object is in the new state
Ready: after the newly created thread is started (), it will enter the thread queue and wait for the CPU time slice. At this time, it has met the running conditions, but it has not been allocated to the CPU.
Run: the process in the ready state is scheduled and obtains the CPU, and enters the running state. The run() method defines the operation and function of the thread
Blocking: under special circumstances, when the input / output operation is suspended or executed artificially, give up the CPU and temporarily suspend its execution to enter the blocking state
Death: the thread has completed all its work and is forced to terminate in advance or terminated due to an exception
1.2 switching relationship of five states
2. Thread synchronization (key)
To solve the thread safety problem
2.1 problem raising - multi window ticket selling
Duplicate ticket
Wrong ticket
analysis:
* 1,In the process of buying tickets, there are duplicate tickets and wrong tickets--->A thread safety problem has occurred * 2,Cause of the problem: when one thread operates the ticket, other threads also participate in the ticket operation when the operation has not been completed * 3,Solution: when a thread is operating ticket Other threads cannot participate until the operation of the current thread ends.Finally, even if the current thread is blocked, it cannot be changed
- The uncertainty of multi thread execution leads to the uncertainty of execution results
- Operation of multiple thread heap sharing data
2.2 solving thread safety problems through thread synchronization mechanism in Java
2.2. 1. Method 1: synchronized code block
2.2. 1.1 synchronous code block solves the thread safety problem of implementing Runnable interface class
synchronized(Synchronization monitor){ //Code to be synchronized } Note: 1. The code that operates the shared data is the code that needs to be synchronized 2,Synchronization monitor(lock),The object of any class can act as a lock Requirement: multiple threads must be shared**Same lock**
Modify the implementation class code:
class Window1 implements Runnable{ private int ticket = 100; //1. Create a new object of any class Object obj = new Object(); @Override public void run() { while (true) { //2. Lock code that operates on shared data synchronized (obj) { if (ticket > 0) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } else break; } } } }
Add: the synchronization monitor here can be an object of any class and unique. Note that the parameter here can also be the current object itself, that is, the parameter here can be (this)
synchronized(this){//synchronized (obj) { if (ticket > 0) { ticket--; System.out.println(getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } else break; }
2.2. 1.2 synchronous code block solves the Thread safety problem of implementing Thread class
Subclass Code:
class Window extends Thread{ private static int ticket = 100; //1. In order to ensure the same seat when "locked", the chair class needs static decoration private static Object obj = new Object(); Window(){} Window(String name){ super(name); } @Override public void run() { while (true) { //2. Lock synchronized (obj) { if (ticket > 0) { ticket--; System.out.println(getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } else break; } } } }
Add: the synchronization monitor here can be (current class name. Class)
synchronized (Window.class) {//The class is also an object, and the class is loaded only once if (ticket > 0) { ticket--; System.out.println(getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } else break; }
2.2. 2. Mode 2: synchronization method
If the code that operates on shared data is completely declared in a method, we can synchronize this method
2.2. 2.1 the synchronization method solves the thread safety problem of implementing Runnable interface class
Implementation class:
class Thread2 implements Runnable{ private int ticket = 100; @Override public void run() { while (true) { show(); } } private synchronized void show(){//Synchronization monitor this at this time if (ticket > 0) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } } }
2.2. 2.2 the synchronization method solves the Thread safety problem of implementing Thread class
class Window1 extends Thread{ private static int ticket = 100; Window1(){} Window1(String name){ super(name); } @Override public void run() { while (true) { show(); } } private static synchronized void show(){//Sync monitor Window1 class if (ticket > 0) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket--; System.out.println(Thread.currentThread().getName() + "A ticket is sold at the window,Current remaining tickets" + (ticket)); } } }
2.2. 3 summary of synchronization methods
* The synchronization method still involves the synchronization monitor, but does not need to be declared explicitly * wrong static The synchronization monitor is this * static The monitor is the current class itself( Xxxx.class)
2.2. 4 advantages and disadvantages of synchronization
Advantages: solves the thread safety problem
Insufficient: when operating synchronization code, other threads wait indiscriminately. Equivalent to a single thread, low efficiency
2.2. Two problems of synchronization method——
2.2. 5.1 rewrite singleton mode (lazy) to thread safe
class Bank{ private Bank(){} private static Bank instance = null; public static Bank getInstance(){ //Mode 1: poor efficiency /* synchronized (Bank.class){ if (instance == null) { instance = new Bank(); } return instance; }*/ //Mode 2: if(instance == null ){ synchronized (Bank.class){ if (instance == null) { instance = new Bank(); } } } return instance; } }
2.2. 5.2 deadlock problem
Causes of deadlock
* Different threads occupy the synchronization resources needed by the other party and do not give up. They are waiting for the other party to give up the resources they need, forming a thread deadlock * There will be no exception or prompt after deadlock, but all threads are blocked and cannot continue
Deadlock code example
public class ThreadTest { public static void main(String[] args) { StringBuffer s1 = new StringBuffer(); StringBuffer s2 = new StringBuffer(); new Thread(){ @Override public void run() { synchronized(s1){ s1.append("a"); s2.append("1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s2){ s1.append("b"); s2.append("2"); System.out.println(s1);; System.out.println(s2); } } } }.start(); new Thread(new Runnable() { @Override public void run() { synchronized(s2){ s1.append("C"); s2.append("3"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (s1){ s1.append("D"); s2.append("4"); System.out.println(s1);; System.out.println(s2); } } } }).start(); } }
Solution to deadlock
* Specialized algorithms * Minimize the definition of synchronization resources * Try to avoid nested synchronization
2.3 solving thread safety problems - mode 3 lock lock
public class LockTest { public static void main(String[] args) { Window w1 = new Window(); Thread t1 = new Thread(w1); Thread t2 = new Thread(w1); Thread t3 = new Thread(w1); t1.setName("Window one"); t2.setName("Window II"); t3.setName("Window three"); t3.start(); t2.start(); t1.start(); } } class Window implements Runnable{ private int ticket = 100; //Instantiate ReentrantLock private ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true){ try { //Call lock() method lock.lock(); if (ticket > 0) { try { sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+":Ticket No.:"+ticket); ticket--; }else break; }finally { //3. Call unlock() to unlock the method lock.unlock(); } } } }
2.4 similarities and differences between synchronized and lock
2.4. 1 same
Can solve thread safety problems
2.4. 2 different
synchronized: automatically release the synchronization monitor after executing the corresponding synchronization code
Lock needs to manually start synchronization lock(), and it also needs to be manually implemented (unlock()) at the end
Priority order
Lock > > sync code block > > sync method