Writing in the front

It has been a while since I wrote [High Concurrency topic], and some readers have left comments saying that concurrent programming is very difficult. I have learned a lot of knowledge, but I don’t know how to start in the actual work. For an online concurrency problem, and do not know the cause of the problem. For concurrent programming, it feels like you’ve mastered it, but really using it is not!

In fact, the essence of this phenomenon is not a thorough understanding of the essence of concurrent programming, and the key to learn concurrent programming is to understand three core issues: division of labor, synchronization and mutual exclusion

Division of labor

The official explanation is: division of labor is to divide a relatively large task into multiple tasks of appropriate size and hand them to appropriate threads to complete, emphasizing performance.

If you don’t understand what division of labor is, we can make an assumption here. Suppose you are the CEO of a XXX listed company and your job is how to manage your company well. However, in terms of how to manage the company well, there are more tasks involved. We can regard it as a big task, which can include: personnel recruitment and management, product design and development, operation and promotion, corporate tax and so on. After that refinement so many tasks to you a person to do, surely you must be broken. Even if you can hold, estimate you a person to complete all this task, that day lily also cool! By that time, estimate you will secretly hide in the corner to sing “cool cool”…

So, if you really want to manage your company, you need to put these task decomposition, the division of refinement, the task of personnel recruitment and management to the human resources department to finish, to complete the product design to the design department, product development to the development department to complete, operating and promotion to the operations and Marketing Department to complete, Leave corporate tax affairs to the finance department. At this point, your task is to keep abreast of the work of each department, plan and coordinate the work of each department, and think about how to plan the future of the company.

In fact, when you break down the tasks of managing the company and divide them up, you will find that the work of each department is carried out in parallel. For example, when the human resource department is managing the performance appraisal of employees, the product design and development department is designing and developing the company’s products. Meanwhile, the company’s operation department is communicating with the design and development department on how to better improve the company’s products, while the promotion department is intensifying its efforts to publicize and promote the company’s products. The financial department is counting and calculating the company’s financial statements. Everything was so organized!Therefore, it is very important to arrange the right people to do the right things in practical work. The same applies to the world of concurrent programming. Delegating all tasks to a single thread is like delegating everything to your company. By the time you’re done, the day lily is cold. So, in concurrent programming, we also need to break down the tasks and assign them to the appropriate threads.

In the world of concurrent programming, there is another problem: assigning tasks to appropriate threads. In other words, do not delegate tasks that should be performed by the main thread to child threads, otherwise, the problem will not be solved. It’s like the CEO of a company leaving it up to a product developer to figure out how to plan the company’s future. Not only does it fail to plan the company’s future, it runs counter to the company’s values.

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

synchronous

In concurrent programming, synchronization mainly refers to how one thread completes a task and informs other threads to continue, with emphasis on performance.

After splitting the tasks and assigning them to each person, it’s time to synchronize each person’s tasks.

Assume that Xiaoming is a front-end developer, and his rendering page data needs to wait for Xiaogang’s interface to complete, while Xiaogang’s writing interface needs to wait for Xiaoli’s service development to complete. In other words, there is a dependency relationship between tasks. After the previous task is completed, the next task can be carried out.

For the actual work, the synchronization of such tasks, most rely on interpersonal communication, Li finished writing the service, tell Xiaogang, Xiaogang immediately interface development, such as the completion of xiaogang interface development, and told Xiaoming, Xiaoming immediately call the interface to render the returned data on the page.

This synchronization mechanism maps to the world of concurrent programming, where a thread notifies subsequent threads to perform a task once it has completed it.

For this synchronization between threads, we can use the following if pseudocode to represent it.

if(Previous task completed){Execute current task}else{continue to wait for the execution of the previous task}Copy the code

In order to determine whether the previous task has been completed in a timely manner, we can also use the while pseudocode to express it.

while(Previous task not completed){continue to wait for previous task execution} executes the current taskCopy the code

The meaning of the pseudo-code above is the same: when the condition of the thread execution is not met, the thread needs to continue to wait, once the condition is met, the waiting thread needs to wake up to continue to execute.

A typical scenario in concurrent programming is the producer-consumer model. When the queue is full, the producer thread needs to wait. When the queue is not full, the producer thread needs to wake up. When the queue is empty, the consumer thread needs to wait, and when the queue is not empty, the consumer needs to wake up. We can use the following pseudocode to represent the producer-consumer model.

  • producers
while{producer thread waiting} wakes up producersCopy the code
  • consumers
while{consumer waits} wakes up the consumerCopy the code

The Java SDK provides utility classes for synchronizing threads, such as CountDownLatch, CyclicBarrier, and so on.

The mutex

Only one thread is allowed to access a shared variable at a time, emphasizing that the thread performs the task correctly.

In the field of concurrent programming, division of labor and synchronization emphasize the performance of executing tasks, while mutual exclusion between threads emphasizes the correctness of executing tasks, that is, thread safety. If multiple threads access the same shared variable at the same time, unintended consequences can occur, and these unintended consequences are mainly caused by thread visibility, atomicity, and orderliness issues. At the heart of the problem of visibility, atomicity, and orderliness is mutual exclusion.

Mutual exclusion can be described as a real-world scenario in which cars from multiple branches of the road need to merge into a road that allows only one car to pass at a time, at which point they queue up to enter the intersection.

Java provides synchronized, Lock, ThreadLocal, and final keywords to solve the problem of mutual exclusion.

For example, using synchronized as an example of mutual-exclusion between threads, the pseudocode is shown below.

// Modify methods
public synchronized void xxx(a){}// Decorates the code block
public void xxx(a){
    synchronized(obj){
        
    }
}
// Decorates the code block
public void xxx(a){
    synchronized(XXX.class){
        
    }
}
// Decorate static methods
public synchronized static void xxx(a){}Copy the code

conclusion

Concurrent programming aims to maximize the use of computer resources, improve the performance of program execution, which requires the division of labor and synchronization between threads to achieve, in order to ensure performance at the same time, but also to ensure the safety of threads, which also needs to ensure the mutual exclusion between threads. The difficulty of concurrent programming is often caused by visibility, atomicity and orderliness. Therefore, when we learn concurrent programming, we must first understand the division of labor, synchronization and mutual exclusion between threads.

Big welfare

WeChat search the ice technology WeChat 】 the public, focus on the depth of programmers, daily reading of hard dry nuclear technology, the public, reply within [PDF] have I prepared a line companies interview data and my original super hardcore PDF technology document, and I prepared for you more than your resume template (update), I hope everyone can find the right job, Learning is a way of unhappy, sometimes laugh, come on. If you’ve worked your way into the company of your choice, don’t slack off. Career growth is like learning new technology. If lucky, we meet again in the river’s lake!

In addition, I open source each PDF, I will continue to update and maintain, thank you for your long-term support to glacier!!

Write in the last

If you think glacier wrote good, please search and pay attention to “glacier Technology” wechat public number, learn with glacier high concurrency, distributed, micro services, big data, Internet and cloud native technology, “glacier technology” wechat public number updated a large number of technical topics, each technical article is full of dry goods! Many readers have read the articles on the wechat public account of “Glacier Technology” and succeeded in job-hopping to big factories. There are also many readers to achieve a technological leap, become the company’s technical backbone! If you also want to like them to improve their ability to achieve a leap in technical ability, into the big factory, promotion and salary, then pay attention to the “Glacier Technology” wechat public account, update the super core technology every day dry goods, so that you no longer confused about how to improve technical ability!