Now let’s look at the second problem in concurrent programming, the atomicity problem. So what is our goal to learn about atomic problems? In the learning process, we are divided into two steps. The first step is to introduce the concept of atomicity, and the second step is to demonstrate the problem of atomicity through a case study.

Let’s look at the concept of atomicity first, we also have to look at the premise, first of all, ah also have multiple threads, if there is no competition in a county is not obvious problem. Second, we need to have shared variables that multiple threads operate on.

Atomicity means that in one or more operations, either all operations are performed without interruption by other factors, or none are performed at all.

Case study:

Objective: To demonstrate atomicity problems

Steps:

1. Define a shared variable number. 2. Perform the ++ operation on number 1000. 3. Use 5 threads.

Public class AtomicityTestDemo01 {// 1, define a shared variable number private static int number = 0; Public static void main(String[] args) throws InterruptedException {// 2 () -> { for (int i = 0; i < 1000; i++) { number++; }}; List<Thread> list=new ArrayList<>(); For (int I = 0; i < 5; i++) { Thread t = new Thread(increment); t.start(); list.add(t); } for(Thread thread:list){ thread.join(); } System.out.println("number="+number); }}Copy the code

So the way we think about it, five threads, each doing a thousand times I ++, normally should be equal to 5,000, so let’s run it and see what happens, it could be 5,000, it could be less than 5,000. The running result of the program is shown in the figure below.

So why is it so much less? So this is due to I ++ it’s multiple operations. And it’s being done by multiple threads, so there’s no guarantee of atomicity for I ++. Let’s disassemble to see how many steps this I ++ is made up of.

We can open it on the command line, other command lines, disassemble it through the bytecode file, and see some bytecode instructions.

javap -p -v 
Copy the code

-p: displays the private information, and -v: displays the details. There are four bytecode instructions for number ++. From this we can see that the number ++ is composed of four instructions. One thread is fine, but in the case of multiple threads there are atomicity problems.

Let’s analyze the atomicity problem, as shown in the figure below. Then we’ll make a pact from now on. Let the red arrow represent the main thread.

In our program, the main thread is executed from the main method, and the Runnble is not executed. The Runnble is created by creating 5 threads to execute the Runnble. Here are five threads that are a little bit tricky to analyze. Let’s say we create two threads here, and both of them, it’s going to do number plus plus. And let’s assume that the value of number is 0. Let’s say that the first thread (t1 thread) executes number ++ first, and there are four instructions. The first instruction getstatic actually fetches number 0. Step down to the instruction iconst_1, which prepares a constant 0. So let’s say we go one step further, and we execute iadd, and we add number = 0 to 1, and we get 1.

But even though there is no assignment, the CPU cuts to another thread (t2 thread) to execute. So another thread is also going to execute number++, and there are also four specified to execute. Getstatic = 0 getStatic = 0 getstatic = 0 So once it gets there, the thread goes down, prepares a 1, then executes iadd, and the t2 thread changes to 1. So let’s say this thread continues to execute, pustatic, and it assigns this 1push to number. At this point, the T2 thread is finished. Let’s say the CPU cuts to t1 again, and it’s going to execute pustatic, but it’s going to push 1, so the number is still going to be 1.

In this case, we see two threads executing number ++. The value of number should be 2, because there are four instructions with no guarantee of atomicity, and we find that the result is only one increment, which causes the data error.

So the reason for this problem is that there are two threads operating on number ++, it’s multiple statements, and one thread is in the middle of executing, and then another thread is executing, and the second thread interferes with the first thread, so there’s no guarantee of completeness.

Summary: When we do concurrent programming, it is very likely that there will be problems of principle. When one thread is in the middle of operating on a shared variable, it is possible for another thread to operate on a shared variable, interfering with the operation of the previous thread, making the operation of the previous thread not guaranteed atomicity.