Java中synchronized是如何保证原子性的


前言

synchronized 是 Java中重量级别的锁,学习多线程并发的同学肯定都不陌生,那么它是怎么确保多线程并发操作的原子性呢?

这篇文章带你深入了解其中的原理。


一、实现原理

保证同一时间只有一个线程操作共享变量,synchronized保证只有一个线程能拿到锁,能够进入同步代码块执行。

二、代码演示

需求:对一个共享变量num进行+1操作,开启5个线程同时操作,每个线程只能加1000,结果要求加到5000。

  • 代码如下:
package com.study.syn;

import java.util.ArrayList;
import java.util.List;

/**
 * synchronized 原子性原理分析
 */
public class Automicity {
    
    

    /**
     * 全局静态变量(也是共享变量)
     */
    private static int num = 0;

    /**
     * 全局锁
     */
    private static Object obj = new Object();

    public static void main(String[] args) throws InterruptedException {
    
    

        // 对num进行1000次的++操作
        Runnable increment = () -> {
    
    
            for (int i = 0; i < 1000; i++) {
    
    
                synchronized (obj) {
    
    
                    num++;
                }
            }
        };

        // 开启多线程
        List<Thread> list = new ArrayList<>();

        // 开启5个线程
        for (int i = 0; i < 5; i++) {
    
    
            Thread t = new Thread(increment);
            t.start();
            list.add(t);
        }

        for(Thread t : list) {
    
    
            t.join();
        }

        System.out.println("num:" + num);
    }

}
  • 我们可以先试试不在num++的部分加锁,如图所示部分:
    不加锁的代码
  • 让我们多执行几次来看看结果:
    结果1
    结果2
    结果3
  • 可以看到,我们执行了3次,只有一次结果是符合我们的预期的。
  • 我们再把代码还原,看看加了synchronized锁之后会怎样:
    加锁之后的代码
  • 让我们一起看看执行结果:
    加锁结果1
    加锁结果2
    加锁结果3
  • 可以看到加锁后三次结果都符合我们的预期。

三、原理分析

  • 想要了解其中的原理,我们需要查看class文件的汇编的结果
  • 找到class文件,执行如下命令:
javap -p -v xxx.class

汇编

  • 找到num++ 那段代码:
    num++代码
  • 我们再把同步锁synchronized去掉,再执行一次汇编,看看有什么不同:
    不带同步锁的代码
  • 从以上可以对比出,加了synchronized之后多出了两个行代码,分别是:
    • 代码块开始部分:monitorenter
    • 代码块结束部分:monitorexit
  • 关于monitor的实现大家可以看看hotspot的源码,是C++写的(OpenJDK8源码下载地址
    C++ monitor源码
  • monitro中有当前拥有锁的线程信息:
    当前拥有锁的线程
  • 也就是说只有这个_owner线程具有执行monitor代码块的权限,从而确保了共享变量同一时间只有一个线程在操作,从而保证了原子性。

总结

Java中synchronized通过控制同一时间可进入代码块的线程有且只能有一个,来保证其原子性。

猜你喜欢

转载自blog.csdn.net/yezhijing/article/details/128505506
今日推荐