Simple test of blocking synchronization and non-blocking synchronization performance in Java thread security

Keywords: Java jvm JDK

Excerpt from Professor Zhou Zhiming's "Deep Understanding of Java Virtual Machine: Advanced Features and Best Practices of JVM" 13.2.2 Thread Safety Implementation Method

1. Noun Interpretation

Synchronization is to ensure that shared data is accessed by only one thread at the same time when the lock thread accesses shared data concurrently.

Mutual exclusive synchronization (blocking synchronization) is a pessimistic concurrency strategy. It is always believed that as long as the correct synchronization measures (locking) are not done, there will be problems.

The most important problem of blocking synchronization is the performance problem caused by thread blocking and wake-up, because after JDK 1.2, Java thread model is replaced by native thread model based on operating system. If you want to block and wake up a thread, you need the help of operating system to complete, which requires the conversion of user mode to kernel mode, which will take a lot of time.

Non-blocking synchronization: With the development of hardware instruction set, we have another option: an optimistic concurrency strategy based on conflict detection, which saves a lot of time without suspending threads, such as CAS (compare and swap) instructions.

2. Start testing

The first method of locking:

    static int a=0;
    public static void lock() {
        Thread[] threads=new Thread[50];
        for(int i=0;i<threads.length;i++){
            threads[i]=new Thread(new Runnable() {
                
                @Override
                public void run() {
                    for(int i=0;i<100000;i++){
                        synchronized(Main.class){
                            a++;
                        }
                    }
                }
            });
            threads[i].start();
        }
        while(Thread.activeCount() > 1){
            Thread.yield();
        }
        System.out.println(a);
    }

The second CAS mode:

    static AtomicInteger integer=new AtomicInteger(0);
    public static void cas() {
        Thread[] threads=new Thread[50];
        for(int i=0;i<threads.length;i++){
            threads[i]=new Thread(new Runnable() {
                
                @Override
                public void run() {
                    for(int i=0;i<100000;i++){
                        integer.incrementAndGet();
                    }
                }
            });
            threads[i].start();
        }
        while(Thread.activeCount() > 1){
            Thread.yield();
        }
        System.out.println(integer.get());
    }

3. Conclusion: Running the two methods, 50 threads, 100,000 self-increasing, output time difference, we can see the difference between performance.

lock method averages 1 270 ms

cas method averages 175 MS

You can see the huge difference between blocking synchronization and non-blocking synchronization, and you can also see that Java thread user-mode kernel-mode switching consumes a lot of processor time.

Posted by marms on Sun, 27 Jan 2019 08:54:14 -0800