Basic knowledge review of multithreading
1) difference between process and thread
Process: After the program runs, a QQ, wechat, etc. is a process. Threading: A thread is the smallest unit in a process. To put it simply, a thread is a different execution path in a program. Procedure: QQ is a program, a program on hard disk.
2) difference between thread run method and start method
public class T01_WhatIsThread { //Create a new static internal class to inherit thread, modify the thread for 1 second, and input T1. private static class T1 extends Thread { @Override public void run() { for(int i=0; i<10; i++) { try { TimeUnit.MICROSECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("T1"); } } } //main method public static void main(String[] args) { new T1().run(); //new T1().start(); for(int i=0; i<10; i++) { try { TimeUnit.MICROSECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("main"); } } } //output T1 T1 main main //At this time, note that the execution result of the start method is quite different from that of the 18run method. T1 main T1 main #Conclusion the execution path of the start method of therad is in the form of branches, while the run method is executed successively from top to bottom.
3) common implementation methods of multithreading
//There are three main ways to implement threads public class T02_HowToCreateThread { //How to integrate threads static class MyThread extends Thread { @Override public void run() { System.out.println("Hello MyThread!"); } } //Implement the Runnable interface static class MyRun implements Runnable { @Override public void run() { System.out.println("Hello MyRun!"); } } //Three different running modes of threads public static void main(String[] args) { new MyThread().start(); new Thread(new MyRun()).start(); //lamda expression to execute a thread new Thread(()->{ System.out.println("Hello Lambda!"); }).start(); } } // lamda expression is also a way, thread pool is also a way //Executors.newCachedThreadPool(); //Get a thread through the thread pool, and the thread still needs to execute the method of runable or start.
4) the most basic method of thread
-
4.1 sleep
- How long does the current thread sleep? It is executed by other threads
-
4.2 join
- It is often used to wait for another thread to finish, that is, to ensure the orderly execution of the thread.
//Test join thread static void testJoin() { Thread t1 = new Thread(()->{ //Thread 1 created 10 threads for(int i=0; i<10; i++) { System.out.println("A" + i); try { //Sleep 500 ms per thread Thread.sleep(500); //TimeUnit.Milliseconds.sleep(500) } catch (InterruptedException e) { e.printStackTrace(); } } }); //Thread 2 Thread t2 = new Thread(()->{ try { //Thread 1 joined. Wait for thread 1 to end t1.join(); } catch (InterruptedException e) { e.printStackTrace(); } //This code will not be executed until thread 1 is finished for(int i=0; i<10; i++) { System.out.println("B" + i); try { Thread.sleep(500); //TimeUnit.Milliseconds.sleep(500) } catch (InterruptedException e) { e.printStackTrace(); } } }); //Start separately t1.start(); t2.start(); } #results of enforcement A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 B0 B1 B2 B3 B4 B5 B6 B7 B8 B9
- It is often used to wait for another thread to finish, that is, to ensure the orderly execution of the thread.
-
4.3 yield
- The current thread leaves first and returns to the ready state. Whether the thread will be executed immediately by the CPU or the thread already waiting in the waiting queue will not necessarily be executed first. Watch competition
State diagram of threads
- Ready running is in the Runnable state.
- The related method of TimedWaiting means that the runnable state will be restored automatically as soon as the time arrives.
- Waiting state means that you must be awakened to enter Runnabel state.
- Synchronized will enter a blocking state before getting the lock of the synchronized code block. After getting the lock, the thread will run.
- Terminated thread stopped
- It is not recommended to use Thread stop method to forcibly stop threads. There is a security problem.
-
Some notes on interrupt:
#The thread enters the blocking state through wait(), at this time, the thread is interrupted through interrupt(); #Calling interrupt() will immediately set the thread's interrupt flag to "true", but because the thread is blocked, the "interrupt flag" will be cleared to "false" immediately, and an exception of InterruptedException will be generated. #We will catch this exception, and then handle the subsequent behavior of the thread according to the business logic. #Code example @Override public void run() { try { // 1. isInterrupted() guarantees that the thread will be terminated as long as the interrupt flag is true. while (!isInterrupted()) { // Perform task... } } catch (InterruptedException ie) { // 2. InterruptedException exception guarantees that when the InterruptedException exception is generated, the thread is terminated. } } //Interrupt is rarely used to control business scenarios. The normal use is to interrupt a thread for a long time.
-
A small example of thread state
static class MyThread extends Thread { @Override public void run() { System.out.println(this.getState()); for(int i=0; i<4; i++) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(i); } } } public static void main(String[] args) { Thread t = new MyThread(); System.out.println(t.getState()); t.start(); try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(t.getState()); } #Output result NEW RUNNABLE 0 1 2 3 TERMINATED
synchronize lock
-
Note that the lock is the object, not the code
For example:
public class T { private int count = 10; private Object o = new Object(); public void m() { synchronized(o) { // **To execute the following code, any thread must first obtain the lock of o** count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } } } #problem //If there are two different objects, O and o1 in the above code, who is the lock? Of course, lock o. ```
-
Several lock forms of synchronize
-
Lock this
private int count = 10; public void m() { synchronized(this) { //To execute the following code, any thread must first obtain this lock count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } }
-
Lock method
private int count = 10; public synchronized void m() { //Equivalent to synchronized(this) when the method's code executes count--; System.out.println(Thread.currentThread().getName() + " count = " + count); }
-
Lock static method
private static int count = 10; public synchronized static void m() { //This is equivalent to synchronized(T.class) count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } public static void mm() { synchronized(T.class) { //Consider whether it's OK to write synchronized(this) here? (no, because there is no new,) count --; } }
-
Small thinking
1) how do the following threads output? 2) what's the difference after adding synchronize? 3) what's the difference after adding volatile
private /*volatile*/ int count = 100; public /*synchronized*/ void run() { count--; System.out.println(Thread.currentThread().getName() + " count = " + count); } public static void main(String[] args) { T t = new T(); for(int i=0; i<100; i++) { new Thread(t, "THREAD" + i).start(); } } #1 the number of duplicates or actual subtractions in the print column is inconsistent with the number printed. //Abnormal part of print result extraction THREAD81 count = 37 THREAD70 count = 37 #2 synchronize ensures both visibility and consistency #3 volatile ensures visibility. This variable is found by threads immediately after it is changed. #4. If you add synchronize, you don't have to add volatile.
- The same thread can drop the locked and unlocked methods at the same time, which does not cause a method to have a lock, and the unlocked method cannot be executed.
- Whether the read method and write method need to be locked to keep consistent depends on the specific business logic. If write lock and read lock are not available, it is possible to dirty read data, which depends on the business. Reading lock will greatly reduce the efficiency of reading.
- synchronize is a reentrant lock. If the locked method 1 is called, the locked method 2 will be called. If it cannot be reentrant, a deadlock will occur.
-
If an exception occurs to the $\ color{red} {program, the lock will be released by default}$
public class T { int count = 0; synchronized void m() { System.out.println(Thread.currentThread().getName() + " start"); while(true) { count ++; System.out.println(Thread.currentThread().getName() + " count = " + count); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } if(count == 5) { int i = 1/0; //If you throw an exception here, the lock will be released. If you want not to be released, you can catch here, and then let the loop continue. System.out.println(i); } } } }} public static void main(String[] args) { T t = new T(); Runnable r = new Runnable() { @Override public void run() { t.m(); } }; new Thread(r, "t1").start(); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } new Thread(r, "t2").start(); } } #//If the printing result is abnormal, t2 will be locked. Continue execution t1 count = 2 t1 count = 3 t1 count = 4 t1 count = 5 t2 start Exception in thread "t1" t2 count = 6 java.lang.ArithmeticException: / by zero at com.mashibing.juc.c_011.T.m(T.java:27) at com.mashibing.juc.c_011.T$1.run(T.java:39) at java.base/java.lang.Thread.run(Thread.java:844) t2 count = 7
- An overview of the underlying upgrade of synchronize
Recommended articles Small segment of lock upgrade
Biased lock (who comes first, who biases) ---
Competing for spin locks, (spin 10 times or JDK is currently set to spin more than half the number of CPU cores)
If the spin limit is exceeded, the heavyweight lock is upgraded, which is an OS level lock and enters the waiting queue. -
Lock usage scenario:
$\ color{red} {few threads, fast lock code execution, using spin lock}$ $\ color{red} {multiple threads, long lock code execution, lock with OS weight}$
-
- summary
The concept of thread, the way to enable thread, and the introduction of common methods.
State machine of thread,
synchronize locks are objects, not code.
Centralized mode of synchronize lock
Upgrade of the lock for synchronize.
Abnormal lock. The default is to discard the lock. Unless catch skips the loop.
Biased lock, spin lock (fair, unfair) heavyweight lock. - The author QQ 68335397 has questions to correct or discuss learning, leave a message.