Java High Concurrency Core Points|Series 5|CPU Memory False Sharing

Mentioned in the previous section: pseudo-sharing, let's talk about it today.

So what is false sharing?

This has to start with the cache structure of the CPU. As shown in the figure below, the CPU generally has three levels of cache, level 1, level 2, and level 3. The higher the upper and the closer to the CPU, the faster the speed and the higher the cost. That is to say, in terms of speed: Level 1 > Level 2 > Level 3.

 Speaking of which, we need to understand a very important concept: cache lines. What is a cache line?

First, let's look at these levels of caches. Among them, the level 1 and level 2 caches are private to the CPU core, that is to say, each core will not share the level 1 and level 2 caches, so how do they communicate or share data? ?

The answer is: Level 3 cache, as shown below:

 Then, in what way is the cache shared between core1 and core2?

The answer is: cache lines!

What is a cache line? Simply put, it is the smallest unit of shared data between CPU cores. As shown in the figure below: x and y are in the same cache line, and the x, y values ​​are exchanged each time the CPU cores communicate, and the two values ​​can be shared at the same time. Is it very efficient?

Yes, in general, if x and y belong to the data in the array, it can achieve the function of efficiently sharing data, but the problem comes again: if x and y do not belong to the same array, x belongs to core1, and y It belongs to core2. At this time, if core1 updates x, the y value will be invalid. Why is it invalidated because they are on the same cache line. At this time, only after the cache line is flushed to the main memory, the corresponding cache line in other cores will be set as expired data, and when the cache line is flushed to the memory, there is a certain delay. Among them, other CPU cores cannot know your update. Then when the kernel core2 reads the value of Y again, since the data in the cache of L1 has become invalid, it needs to be obtained from L3, then put into L2, and then into L1. In this way, core 2 needs to read the Y value from the L3 level cache. But it is obviously the value of X modified by core core1, but it affects core 2 to read the value of Y. Similarly, if kernel 2 modifies the value of Y, it will also affect kernel 1 to read the value of X.

Simply put, x, y are placed in the same cache line, and they belong to the data values ​​of different CPU cores (in fact, CPU cores are also in the code: threads). That would invalidate the cache by updating one of the values ​​each.

This is the famous false sharing problem.

Is there any solution?

some.

The scenario is: cache line fill.

 Going back to the above example, if x and y are placed in the same cache line, it will cause false sharing. It's very simple, then don't put them together!

For example: x has 8 bytes (bytes), and the general cache line has a total of 64 bytes. For the other remaining positions, we can just fill them with predetermined empty variables. The code is as follows (java6 version):

  public final static class VolatileLong { public volatile long x= 0L ; public long p1, p2, p3, p4, p5, p6,p7 ; //cache line filling }  

 At this time, core1 updates the x value, which will not affect the y value, resulting in a false sharing problem.

The above code is the solution for java6.

Scheme under JAVA 8

In JAVA 8, cache line filling is finally supported natively by JAVA. A @Contended annotation has been added in JAVA 8. Adding this annotation will automatically fill in the cache line, as shown in the following code:

import sun.misc.Contended;

@Contended
public class VolatileLong {
    public volatile long value = 0L;  
}

When executing, the virtual machine parameter -XX:-RestrictContended must be added, and the @Contended annotation will take effect. A lot of articles leave this out, and then it doesn't actually work.

This is the solution to false sharing, how easy it is!

This series is over!

If you readers have any comments or suggestions, please feel free to complain!

Related Posts