Three core issues that must be understood to learn concurrent programming

Some readers and friends left a message saying that concurrent programming is difficult and I have learned a lot of knowledge, but I can't get started in actual work. Regarding a concurrency problem that occurs online, I don't know what is causing the problem. For concurrent programming, it seems to be mastered, but it is not the case when it is really used!
In fact, the essential reason for this phenomenon is that there is no thorough understanding of the essence of concurrent programming, and the key to learning concurrent programming is to understand three core issues: division of labor, synchronization and mutual exclusion

Friends who need more Java knowledge and interview questions can click the link below to get it for free

Link: 1103806531 Password: CSDN

Insert picture description here

Division of labor

The more official explanation is: Division of labor is to split a relatively large task into multiple tasks of appropriate size, and hand them over to the appropriate thread to complete. The emphasis is on performance.

If you still cannot understand what the division of labor is, here, we can make an assumption. Suppose you are the CEO of a XXX listed company. How do you manage your company? However, in terms of how to manage a company well, there are more tasks involved. We can regard it as a big task. If you look closely, this big task can include: personnel recruitment and management, product design And development, operation and promotion, corporate taxation, etc. After refining so many tasks to you alone, you must have collapsed. Even if you can hold on, it is estimated that if you complete all these tasks alone, the day lily will be cold! At that time, it is estimated that you will secretly hide in the corner and sing "Cool". . .

Therefore, if you really want to manage your company well, you need to decompose these tasks, divide labor, and hand over the recruitment and management tasks to the human resources department to complete, and the product design to the design department to complete , The product development is handed over to the development department to complete, the operation and promotion are handed over to the operation and marketing department to complete, and the company tax is handed over to the financial department to complete. At this time, your task is to understand the work of each department in time, plan and coordinate the work of each department, and think about how to plan the company's future.

In fact, after you disassemble and refine the tasks of the management company here, you will find that the work between departments is actually executed in parallel. For example, when the human resources department manages the performance appraisal of employees, the product design and development department is designing and developing the company’s products. At the same time, the company’s operations are communicating with design and development on how to better improve the company’s products. The promotion department is stepping up efforts to promote and promote the company's products. The financial department is counting and calculating the company's various financial statements. Everything is so methodical!

Insert picture description here
Therefore, arranging the right people to do the right things is very important in actual work. The same applies to the field of concurrent programming. If you delegate all tasks to one thread for execution, it's like entrusting all the company's tasks to you alone. When things are done, the day lily is also cold. Therefore, in concurrent programming, we also need to disassemble tasks and assign them to appropriate threads for completion.

Insert picture description here
In the field of concurrent programming, there is another issue that needs to be paid attention to: division of labor to the appropriate threads . In other words, the tasks that should be performed by the main thread should not be handed over to the sub-threads, otherwise the problem cannot be solved . This is like how the CEO of a company entrusts a product developer to plan the company’s future. This not only fails to plan the company’s future, it may even run counter to the company’s values.

In the JavaSDK: Executor, Fork/Join and Future are all ways to achieve division of labor.

Synchronize

Synchronization in concurrent programming mainly refers to how to notify other threads to continue execution after a thread finishes its task. The emphasis is on performance.

Split the task and give everyone a reasonable division of labor. The next step is how to synchronize everyone's tasks.

Suppose Xiao Ming is a front-end developer, and he needs to wait for Xiaogang's interface to complete when he renders the page data, and Xiaogang writes the interface and needs to wait for Xiao Li's service development to complete. In other words, there is a dependency relationship between tasks, and the following tasks can only be performed after the previous tasks are completed.

In actual work, most of the synchronization of this task relies on communication between people. After Xiao Li's service is finished, tell Xiaogang that Xiaogang will immediately develop the interface and wait for Xiaogang's interface development to be completed Later, I told Xiao Ming, Xiao Ming immediately called the interface to render the returned data on the page.

Insert picture description here
This synchronization mechanism maps to the field of concurrent programming, that is, after a thread's task is executed, it notifies other subsequent threads to perform the task.

For this kind of synchronization between threads, we can use the following if pseudo code to express.

if(前面的任务完成){
    
    
    执行当前任务
}else{
    
    
    继续等待前面任务的执行
}

If in order to be able to judge whether the previous task has been completed more in time, we can also use the while pseudo code to indicate it.

while(前面的任务未完成){
    
    
    继续等待前面任务的执行
}
执行当前任务

The meaning of the above pseudo code is the same: when the condition of thread execution is not met, the thread needs to continue to wait, and once the condition is met, the waiting thread needs to be awakened to continue execution.

In the field of concurrent programming, a typical scenario is the producer-consumer model. When the queue is full, the producer thread needs to wait, and when the queue is not full, it needs to wake up the producer thread; when the queue is empty, the consumer thread needs to wait, and when the queue is not empty, it needs to wake up the consumer. We can use the following pseudo code to represent the producer-consumer model.

Producer

while(队列已满){
    
    
    生产者线程等待
}
唤醒生产者

consumer

while(队列为空){
    
    
    消费者等待
}
唤醒消费者

In the Java SDK, some tool classes for synchronization between threads are provided, such as CountDownLatch, CyclicBarrier, etc.

Mutually exclusive

At the same time, only one thread is allowed to access the shared variable, which emphasizes the correctness of the thread's task execution.

In the field of concurrent programming, division of labor and synchronization emphasizes the performance of tasks, while mutual exclusion between threads emphasizes the correctness of threads to perform tasks, that is, thread safety . If multiple threads access the same shared variable at the same time, unintended consequences may occur, and such unintended consequences are mainly caused by the visibility, atomicity and order of threads . The core of solving the problems of visibility, atomicity and order is mutual exclusion.

Regarding mutual exclusion, we can use a scene in reality to describe: vehicles at multiple forks need to merge into a road, and this road can only allow one vehicle to pass at a time, at this time, the vehicles need to queue to enter in turn intersection.

The synchronized, Lock, ThreadLocal, and final keywords provided in Java can all solve the problem of mutual exclusion.

For example, we take synchronized as an example to illustrate how to perform mutual exclusion between threads. The pseudo code is shown below.

//修饰方法
public synchronized void xxx(){
    
    
    
}
//修饰代码块
public void xxx(){
    
    
    synchronized(obj){
    
    
        
    }
}
//修饰代码块
public void xxx(){
    
    
    synchronized(XXX.class){
    
    
        
    }
}
//修饰静态方法
public synchronized static void xxx(){
    
    
    
}

to sum up

Concurrent programming aims to maximize the use of computer resources and improve the performance of program execution. This requires division of labor and synchronization between threads to achieve. While ensuring performance, it is also necessary to ensure the safety of threads, which in turn needs to ensure that threads are Mutual exclusion between. The difficulty of concurrent programming is often caused by problems of visibility, atomicity, and order. Therefore, when we learn concurrent programming, we must first understand the division of labor, synchronization and mutual exclusion between threads.

At last

I have also compiled a complete set of video tutorials for architects and systematic materials on java, including java core knowledge points, interview topics, and the latest 20 years of Internet real questions and e-books. Friends in need can click the link below to get it for free!

Link: 1103806531 Password: CSDN

Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/XingXing_Java/article/details/109221209