false sharing in Java

false sharing in Java

1. Introduction
Recently, I was watching the latest version of JVM. It is quite good that the changes of JVM after jdk8 have been introduced more than the previous second version. (Recommend everyone to watch!!!) Then the pseudo-sharing is mentioned in the card table, so there is the following article. (Maybe many big guys have written it, I will write it again to strengthen my own understanding.)

2. What is pseudo-sharing?
Wikipedia's explanation of false sharing: The CPU cache is cached in units of cache lines. When multiple threads modify different variables, and these variables are in the same cache line, it will affect each other's performance. For example: thread 1 and thread 2 share a cache line, thread 1 only reads variable 1 in the cache line, thread 2 modifies variable 2 in the cache line, although thread 1 and thread 2 operate on different variables, because variable 1 It is in the same cache line as variable 2. When variable 2 is modified, the cache line is invalid, and thread 1 has to read from the main memory again, thus causing the cache to be invalid, resulting in performance problems. To better understand false sharing, let's first look at the CPU cache.
Generally speaking, it is caused by threads accessing the cache line at the same time, and the cached data of the data in the cache line is invalid.

3. False sharing problem in java

private static final int DIMENSION_1 = 1024 * 1024;
    private static final int DIMENSION_2 = 62;

    private static long[][] longs;

    public static void main(String[] args) throws Exception {
    
       
    
        longs = new long[DIMENSION_1][];
        for (int i = 0; i < DIMENSION_1; i++) {
    
       
    
            longs[i] = new long[DIMENSION_2];
            for (int j = 0; j < DIMENSION_2; j++) {
    
       
    
                longs[i][j] = 0L;
            }
        }
        System.out.println("starting....");

        final long start = System.currentTimeMillis();
        long sum = 0L;
        for (int r = 0; r < 10; r++) {
    
       
    

            // 1----------------------------
            for (int j = 0; j < DIMENSION_2; j++) {
    
       
    
                for (int i = 0; i < DIMENSION_1; i++) {
    
       
    
                    sum += longs[i][j];
                }
            }
            // 2----------------------------

            // 3----------------------------
//            for (int i = 0; i < DIMENSION_1; i++) {
    
       
    
//                for (int j = 0; j < DIMENSION_2; j++) {
    
       
    
//                    sum += longs[i][j];
//                }
//            }
            // 4----------------------------
        }
        System.out.println("执行时间 = " + (System.currentTimeMillis() - start));
    }

3-4 lines quickly get the reason:

3-4行运算,每次开始内循环时,从内存抓取的数据块实际上覆盖了longs[i][0]到longs[i][5]的全部数据(刚好64字节)。
因此,内循环时所有的数据都在L1缓存可以命中,遍历将非常快。

Reasons why 1-2 lines are slow:

1-2行运算,每次从内存抓取的都是同行不同列的数据块(如longs[i][0]到longs[i][5]的全部数据),但循环下一个的目标,
却是同列不同行(如longs[0][0]下一个是longs[1][0],造成了longs[0][1]-longs[0][5]无法重复利用

4. The pseudo-sharing problem
in java Java 8 has provided an official solution, and a new annotation has been added in Java 8: @sun.misc.Contended. The class with this annotation will automatically complete the cache line. It should be noted that this annotation is invalid by default, and it will take effect only when -XX:-RestrictContended is set when the jvm is started.
At the same time, the @sun.misc.Contended annotation is also used in ConcurrentHashMap to solve false sharing.

/**
     * A padded cell for distributing counts.  Adapted from LongAdder
     * and Striped64.  See their internal docs for explanation.
     */
    @sun.misc.Contended static final class CounterCell {
    
       
    
        volatile long value;
        CounterCell(long x) {
    
       
     value = x; }
    }
-XX:+UseCondCardMark,用来决定是否开启 卡表更新的条件判断。这个是解决内存回收时的卡表判断数据是否是需要回收的数据,来解决伪共享问题。
	但是实际开发中一般很难遇到。如果真的遇到了,那将是一个奇怪知识爆增的时机。

Introducing the article: https://blog.csdn.net/xiamiflying/article/details/80910680