当前位置:网站首页>Summary of multithreading and thread synchronization knowledge
Summary of multithreading and thread synchronization knowledge
2022-07-02 16:00:00 【ZJH'blog】
Multithreading
Program process Threads
Program : Static code , What is not running is called a program
eg: All files in the folder
The collection of all static code included in the whole folder is the programprocess : Is a run of the program or A running program , It's a dynamic process , And has its own production 、 There is 、 The process of extinction —— Life cycle
eg: Running QQ、 Running LOL、 Running 360 Safety guardThreads : Processes can be subdivided into threads , It's an execution path inside the program . If a process can execute multiple threads simultaneously , It supports multithreading .
A thread is the unit of scheduling and execution , There are independent running stacks and program counters , Low cost of thread switching
Multiple threads in a process share the same resource , Therefore, interprocess communication can be more efficient , But it also brings security risks
eg: At the same time, sweep the loopholes 、 crack down on drug trafficking 、 Cleaning up garbage is multithreading , Multithreading has increased cpu utilization
eg: Graphical interfaces are basically multithreaded
eg:QQ At the same time, many people send messages to each otherOne java Applications java.exe At least There are three threads :main() The main thread 、gc() Garbage collection thread 、 Exception handling threads , There can also be memory monitoring The operation log
CPU Single core and multi-core
- Single core CPU: It's actually a fake multithreading , The appearance of multithreading is actually fast switching between different threads ( Time division multiplexing ), It's a kind of concurrency
eg: The same process , Use a single core cpu, Single threading is faster than multithreading , Because there is no thread switching time
- Multicore CPU: Can be implemented in parallel , And
eg: Many mobile phones nowadays are 8 The core , But this 8 The nuclei are not exactly the same , When the mobile phone writes a memo , Call the core with smaller power consumption and weaker function , When playing games, call a stronger but power consuming core
Concurrent 、 parallel
Concurrent : One CPU Execute multiple threads at the same time
parallel : Multiple CPU Execute multiple threads at the same time
Creation and use of Multithread
Traditional multithreading
- Thread has priority 1~10, And it is a statistical priority , Satisfy the law of large numbers
- Thread Class implements the Runnable Interface , You can create threads
- Thread pool is commonly used in development , Thread pools reduce the time it takes to create and destroy threads
- When writing multithreads by yourself , Logic may be correct , But there are several output exceptions that do not conform to multithreading , This may be caused by the unstable time difference between multithreading and screen output
Thread Common methods of class
- void start(): Start thread , And execute the object's run() Method
- void run(): The operation that a thread performs when it is scheduled
- String getName(): Returns the name of the thread
- void setName(String name): Set the thread name
- static Thread currentThread(): Returns the current thread object . stay Thread In subclasses yes this, It is usually used for the main thread and Runnable Callable Implementation class
- static void yield(): Thread concession . Pause the currently executing thread , Give up execution to threads of the same or higher priority If there are no threads of the same priority in the queue , Ignore this method .
- join() : When a program execution stream calls other threads join() When the method is used , The calling thread will Blocked , until join() Method added join Until the thread finishes executing , Low priority threads can also be executed . This method requires try-catch
- static void sleep(long millis):( Specify time : millisecond ) Causes the current active thread to give up on CPU control , Give other threads a chance to be executed , When it's time to queue again . Throw out * InterruptedException abnormal . This method requires try-catch
- stop(): Force thread lifetime to end , It is not recommended to use
- boolean isAlive(): return boolean, Determine if the thread is alive
sleep yield join wait notify The difference lies in the following thread synchronization
Runnable Interface : As Thread Construction parameters of objects
- Compared with direct use Thread, Can achieve “ Multiple inheritance ”
- Thread startup still needs to be implemented Thread class
- new Thread( new MyThread() ) .start To start up
Example :
class MyrunThread implements Runnable {
public void run() {
for (int i = 1; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class RunnableTest {
public static void main(String[] args) {
// One step writing
new Thread(new MyrunThread()).start();
// Two step writing
MyrunThread m1 = new MyrunThread();
Thread M1 = new Thread(m1);
//M1 You can call Thread Class
M1.start();
}
}
Callable Interface : With the help of FutureTask Decoupling
- And Runnable comparison ,Callable More powerful , You can have a return value , You can throw the exception
- Runnable It's rewriting run() Method ,Callable It's rewriting call() Method
- The function of return value needs the help of FutureTask class , And from FutureTask Class object .get() Get the return value
- Because even with Callable Interface implementation , There are also cases where the return value is not required , So introduce FutureTask Class to decouple
- new Thread( new FutureTask( new MyThread() ) ).start To start up
Realization Callable Interface , rewrite call() Method
class Mythread implements Callable<Integer>{
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1 ; i<100 ; i++){
if(i%4==0){
System.out.println(i);
sum+=i;
}
}
return sum;
// The return value here cannot pass Thread Directly obtained
// Need to use FutureTask
}
}
With the help of FutureTask, Realization Thread
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Mythread M1 = new Mythread();// Realization Callable Interface instance
FutureTask F1 = new FutureTask(M1);// Pass in FutureTask in
Thread T1 = new Thread(F1);// Pass in Thread in
T1.start();// start-up
System.out.println(F1.get());
//start function call Method , But it is not necessary to receive the return value
}
}
Thread pool
Advantages compared with tradition
- Traditional thread implementation methods include thread creation Thread to destroy Time for , Threads can be reused , So the thread pool is introduced , Create and destroy threads Change it to Return after use , Not destroyed , Reuse resources , Improve thread utilization , Improve the response speed of the program
- Easy to manage Thread objects in a unified way
- You can control the maximum concurrency
Thread pool model —— Bank
Counter window : Threads , Without destroying
Waiting area : Waiting in line
When the window is not enough : Add threads
When there are no seats in the waiting area : Refusal strategy —— Report an exception or give it to a thread to go left
There are too many free windows : Reduce threads
Thread pool creation
JUC The concurrency toolkit provides ThreadPoolExecutor Creating a thread pool ,ThreadPoolExecutor Yes 8 Parameters , Respectively :
- corePoolSize: Number of core threads —— The number of counter windows that never close
- maximumPoolSize: Maximum number of threads —— The maximum number of windows
- keepAliveTime: Thread lifetime —— How long does it take for a non core thread to be destroyed without receiving a task —— You need to set the unit unit
- unit:TimeUnit.SECONDS or TimeUnit.MICROSECONDS You can wait
- BlockingQueue : Waiting in line ,new ArrayBlockingQueue<>(capacity:10) here capacity The value of the set 10
- ThreadFactory: Thread factory —— No need to create , Call directly Executors.defaultThreadFactory()
- RejectedExecutionHandler: Refusal strategy ——new ThreadPoolExecutor.AbortPolicy() The handler of the rejected task , Throw a RejectedExecutionException
After creating it, use ExecutorService Class object to receive , Then you can directly call
for example : utilize lambda expression
for(){
executorService.execute( ()->{ Thread business logic } );
}// The thread pool will automatically adjust the current number of threads
executorService.shutdown();// Close thread pool
Reference resources :
Thread synchronization
Synchronization of thread synchronization means : Coordinated pace , Run in a predetermined order
Prevent data reading and writing errors caused by concurrency
Locking mechanism
The realization of synchronization is inseparable from the unlocking mechanism , The following common locks
Reference material
Deadlock
Reference resources : Deadlock prevention
Deadlock prevention generally includes :
Handwriting deadlock :
class Mythread implements Runnable{
public void run(){
......
synchronized( lock A){
//A Lock sleeve B lock
synchronized( lock B){
......
}
}
......
}
}
class Youthread implements Runnable{
public void run(){
......
synchronized( lock B){
//B Lock sleeve A lock
synchronized( lock A){
......
}
}
......
}
}
If the lock makes a recursive call , A lock may also cause deadlock
Pessimistic locking
- Think that there are always threads that will operate on the data they are operating
- Use scenarios : Write frequently ; Guarantee safety
- Lock implementation :synchronized keyword 、Lock Interface
Optimism lock
- Think that no thread will operate the data it is operating
- Use scenarios : Read more and write less ; Ensure high efficiency
- Lock implementation :CAS Algorithm
Read the lock (S lock )( Shared lock )
- read-only , for example SELECT
- Add S After locking , Other affairs can only be added S Lock and not add X lock , But the lock keeper himself can add X lock
If business T For data objects A add S lock , The transaction T You can read A But it can't be modified A, Other affairs can only be right again A Add S lock , Instead of X lock , until T Release A Upper S lock . This ensures that other things can be read A, But in T Release A Upper S You can't do it before you lock it A Make any changes .
Write lock (X lock )( Exclusive lock )
- Write , for example INSERT、UPDATE or DELETE
- Add X After locking , Nothing else can be added S Lock and X lock
If business T For data objects A add X lock , Business T You can read A You can also modify A, Other affairs can no longer be right A Add any locks , until T Release A The lock on the . This ensures that the rest of the business is T Release A The lock on can't be read or modified before A.
Fair lock
- Multiple threads sharing the same lock are queued in order , And lock it in line
- private ReentrantLock lockkk = new ReentrantLock(true); It's called fair lock
Handwriting fair lock :
private ReentrantLock lockkk = new ReentrantLock(true);// Fair lock
.........
public void run(){
for(int i = 1;i<=100;i++){
lockkk.lock();// Put on the fair lock lockkk
System.out.print(Thread.currentThread().getName());
Depot(this.account,1000);
// Output content
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}// add sleep The effect is more obvious , To prevent misleading caused by screen output time difference
lockkk.unlock();// Release the fairness lock lockkk
// After that, the call lock The thread of enters the end of the queue , Do not compete with other threads for resources
}
}
Not fair lock
- Multiple threads sharing the same lock are queued in order , But it is not locked in order , Still like synchronized By grabbing
- private ReentrantLock lockkk = new ReentrantLock(false);
private ReentrantLock lockkk = new ReentrantLock(); It's all unfair locks
volatile keyword
- Only variables can be decorated , Such as :private volatile static int phoneNumber = 0;
- Writes to variables do not depend on the current value , if ++i , i+=5 This operation that depends on the original value may still have errors
- This variable is independent : This variable is not included in invariants with other variables
- volatile No need to lock , Than synchronized More lightweight , Will not block threads
- synchronized It can guarantee the visibility , It also guarantees atomicity , and volatile Only visibility is guaranteed , There is no guarantee of atomicity .
synchronized keyword
Why use objects as monitors ?:
because java Of Each object has a built-in lock , When you decorate a method with this keyword , The built-in lock will protect the whole method . Before calling this method , To obtain the built-in lock , Otherwise, it is blocked .
Synchronization method ( Coarse grained lock )
- More cumbersome than synchronized code blocks , It's more expensive
- use this locked , Therefore, there are potential risks
- Synchronization method ( Coarse grained lock ):
A、 Modify the general method : public synchronized void method(){…}, Get the current calling object this The lock on the ;
B、 Modified static method : public static synchronized void method (){…}, Get the lock on the bytecode object of the current class .
Synchronization code block ( Fine grained lock )
- Object monitor : The same object, the same lock , In the same synchronization mechanism
- For monitors this Refers to the current class object ,
for example : use Runnable Interface implementation thread ,run() The method is written as synchronized, So this lock is Runnable The object of , If you use this object as a formal parameter to create multiple threads , Thread synchronization
for example : use extends Direct inheritance Thread,run() The method is written as synchronized, that new A few threads are locked , Lost synchronization function
Lock Interface
Lock The interface can be active in any position lock and unlock, So it's more flexible
ReentrantLock Interface
public class ReentrantLock implements Lock, java.io.Serializable
- Provide fair lock mechanism , and synchronized It's not fair
- boolean tryLock() Method : If you can't get the lock, go back false, Don't like synchronized Have been waiting for
- void lock() locked , And we need void unlock() Active unlocking
- When an exception occurs ,synchronized Will automatically release the lock , and Lock The interface needs to be in try-catch-finally Release the lock manually , Prevent deadlock
- In terms of performance , If threads do not compete fiercely for resources , The performance of the two is similar , and When the competitive resources are very fierce ( That is, a large number of threads compete at the same time ), here Lock The performance is much better synchronized
Example
private ReentrantLock locker = new ReentrantLock(true);// Fair lock
.........
public void run(){
for(int i = 1;i<=100;i++){// Simulated multithreading
locker.lock();// Put on the fair lock lockkk
try{ Possible error code executed
}catch(Exception e){
e.printStackTrace();
}finally{
locker.unlock()
}
}
}
sleep yield join wait notify
First of all, make sure that ,CPU Resource scheduling and thread synchronization are not the same concept , Even without a monitor ( There is no lock ), Also exist CPU Resource scheduling problem ( Also have sleep and yield Method );
And only after locking wait and notify To operate the execution of threads
CPU Resource perspective
- sleep and yield Don't release the lock , So the effect is cpu Resource scheduling
- All static methods , So you can Irrelevant monitors , Irrelevant synchronization
sleep Thread to sleep
- No release lock , Threads with the monitor are still blocked
- Stable transfer cpu resources , Threads of different monitors can execute
- Static methods ,Thread.sleep(123123) used anywhere
yield Thread concession
- No release lock , Threads with the monitor are still blocked
- Unstable transfer cpu resources , Scramble again cpu resources , It may not have obvious effect
- Threads of other monitors need : priority >= call yield The thread of , To compete cpu resources
Thread synchronization angle
- wait notify notifyAll All need to be written in the synchronized code block , For has been obtained Obj Lock operation , Are not static methods
- Grammatically speaking, it means Obj.wait(),Obj.notify Must be in synchronized(Obj){…} In the block .
- functionally wait That is to say, after the thread obtains the object lock , Active release of object lock , At the same time, this thread sleeps . Until another thread calls the object notify() Wake up the thread , To continue to acquire the object lock
wati
- Release CPU Release the lock at the same time
- Get into Waiting pool , Wait for other threads to use obj.notify() Wake up the
- Because it is written in synchronized Block of code , So call obj.wait() Then you need to wait for the code block to finish executing before blocking
notify notifyAll
- Under the same monitor ( Under the same lock ), The former is to wake up a thread randomly , The latter is to wake up all threads
- notify and notifyAll The final effect is to wake up one from the waiting pool , but notify It may cause both threads to hang , Cause obstruction ( All threads are wait Entered the waiting pool , There is no thread to perform wakeup )
Object internal lock
Actually , Each object has two pools , They are lock pool (EntrySet) and (WaitSet) Waiting pool .
- Lock pool : If there are already threads A Got the lock , Now there are threads B Need to get this lock ( For example, you need to call synchronized Decorated methods or need to be implemented synchronized Decorated code block ), Because the lock has been occupied , So threads B Just wait for this lock , At this point, the thread B Will enter the lock pool of this lock .
- Waiting pool : Assuming that thread A After getting the lock , Because some conditions are not satisfied ( For example, in the producer consumer mode, the producer obtains the lock , Then judge that the queue is full ), You need to call the object lock wait Method , So thread A Will give up this lock , And enter the waiting pool of this lock .
If another thread calls the lock notify Method , It will select a thread from the waiting pool according to a certain algorithm , Put this thread into the lock pool .
If another thread calls the lock notifyAll Method , All threads in the waiting pool will be put into the lock pool , And fight for locks .
The difference between locking pool and waiting pool : The thread in the waiting pool cannot acquire the lock , It needs to be awakened into the lock pool , To get the lock .
边栏推荐
- 数字藏品系统开发(程序开发)丨数字藏品3D建模经济模式系统开发源码
- 死锁的条件及解决方法
- PyObject 转 char* (string)
- 可视化技术在 Nebula Graph 中的应用
- 《大学“电路分析基础”课程实验合集.实验六》丨典型信号的观察与测量
- 制作p12证书[通俗易懂]
- Pyinstaller's method of packaging pictures attached to exe
- /Bin/ld: cannot find -lgssapi_ krb5
- 使用 percona 工具给 MySQL 表加字段中断后该如何操作
- Moveit obstacle avoidance path planning demo
猜你喜欢
愛可可AI前沿推介(7.2)
【5G NR】RRC连接释放
图数据库|Nebula Graph v3.1.0 性能报告
Recommended practice sharing of Zhilian recruitment based on Nebula graph
Crawl the information of national colleges and universities in 1 minute and make it into a large screen for visualization!
隐藏在 Nebula Graph 背后的星辰大海
Aiko ai Frontier promotion (7.2)
Idea jar package conflict troubleshooting
爱可可AI前沿推介(7.2)
智联招聘的基于 Nebula Graph 的推荐实践分享
随机推荐
/Bin/ld: cannot find -lpam
【题解】Educational Codeforces Round 82
Fastjson list to jsonarray and jsonarray to list "suggested collections"
Boot 连接 Impala数据库
将点云坐标转换成世界坐标的demo
After the win10 system is upgraded for a period of time, the memory occupation is too high
Ant group's large-scale map computing system tugraph passed the national evaluation
Introduction to Dynamic Planning II (5.647.62)
mysql 计算经纬度范围内的数据
Make p12 certificate [easy to understand]
【idea】推荐一个idea翻译插件:Translation「建议收藏」
Invalid bound statement (not found)解决方法总结
Practice of constructing ten billion relationship knowledge map based on Nebula graph
Flink real-time data warehouse (IX): incremental synchronization of data in MySQL
Application of visualization technology in Nebula graph
How to import a billion level offline CSV into Nepal graph
《大学“电路分析基础”课程实验合集.实验六》丨典型信号的观察与测量
《大学“电路分析基础”课程实验合集.实验四》丨线性电路特性的研究
Multi data source configuration code
又是一年毕业季