Synchronized原理分析

我们先看一个例子

public class SynchronizedDemo  {
    static Integer count=0;
    public static void incr(){
        count++;
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        for(int i=0;i<1000;i++){
            new Thread(()->SynchronizedDemo.incr()).start();
        }
        Thread.sleep(2000);
        System.out.println("result:"+count);
    }
}
复制代码

最后的输出我们可以看一下

一定是一个小于等于1000的值,这是一个比较经典的代码场景了,小于1000的原因也简单就是可见性和原子性的原因
可见性:线程看不到变量的最新值,因为它还没有被另一个线程写回主内存,这个问题被称为“可见性”问题。一个线程的更新对其他线程是不可见的。
原子性: 原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行原子性就是指该操作是不可再分的。 count++看着像是一句代码好像也不能够再怎么拆分步骤,但其实底层是分为好几步的,我们可以使用 javap -v xx.class指令查看对应字节码如下: 发现先是访问这个值然后声明一个常量压入到栈中,然后再加加操作最后就是赋值给静态变量(大概的流程其实就是需要在内存中声明一个变量把原来变量的值赋值给新变量对这个新值进行++最后赋值给初始变量),所以这里就会出现原子性问题如下图所示:

Synchronized的使用

针对上面的问题呢解决方法其实也比较简单就是加锁,加锁之后就能实现多个线程不能同时执行同一个任务修改后的代码如下:

public class SynchronizedDemo  {
    static Integer count=0;
    public static void incr(){
        synchronized (SynchronizedDemo.class) {
            count++;
        }
    }
    public static void main(String[] args) throws IOException, InterruptedException {
        for(int i=0;i<1000;i++){
            new Thread(()->SynchronizedDemo.incr()).start();
        }
        Thread.sleep(2000);
        System.out.println("result:"+count);
    }
}
复制代码

可以发现打印结果一定是1000

当然Synchronized的使用方法不止这一种还有如下三种方式:

  1. 使用对象示例的锁
    public class SynchronizedDemo  {
        static Integer count=0;
        static Object obj = new Object();
        public static void incr(){
            synchronized (obj) {
                count++;
            }
        }
        public static void main(String[] args) throws IOException, InterruptedException {
            for(int i=0;i<1000;i++){
                new Thread(()->SynchronizedDemo.incr()).start();
            }
            Thread.sleep(2000);
            System.out.println("result:"+count);
        }
    }
    复制代码
  2. Synchronized修饰在类方法上
     public class SynchronizedDemo  {
         static Integer count=0;
         public synchronized static void incr(){
             count++;
         }
         public static void main(String[] args) throws IOException, InterruptedException {
             for(int i=0;i<1000;i++){
                 new Thread(()->SynchronizedDemo.incr()).start();
             }
             Thread.sleep(2000);
             System.out.println("result:"+count);
         }
     }
    复制代码
  3. 修改在实例方法上
     public class SynchronizedDemo  {
         static Integer count=0;
         public static synchronized void incr(){
           
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值