深入理解Synchronized实现原理

synchronized简介

众所周知Java使用synchronized关键字实现多线程环境下同步语义,为什么会出现线程安全,会产生什么影响?使用synchronized可以自动帮我们将多线程执行逻辑变为串行执行,保证同一时刻仅有一个线程可以执行synchronized所保护的代码逻辑

synchronized在多线程环境下具有以下语义

1.可见性:一个线程对共享变量的修改,其他线程立即可以得知

2.有序性:cpu以及编译器在不改变代码执行结果的情况下,为了提升执行效率,会对代码进行乱序执行(指令重排序),在单线程下是不会出现任何问题,但是在多线程执行,可能出现意外的结果,有序性是指禁止指令重排序,按照代码原有的逻辑进行执行

3.原子性:对共享变量的修改过程不允许被打断

synchronized使用的三种方式:

1.锁定普通方法,锁住的是当前实例对象

public class SynchronizedMethod {

    public static void main(String[] args) {
        
        SynchronizedMethod sm = new SynchronizedMethod();
        //锁住的sm实例
        sm.read();
        
    }
    
   //在方法上加synchronized 锁住当前实例
    public synchronized void read(){
        System.out.println("I am SynchronizedMethod");
    }

}

2.锁定静态方法,锁住的是当前Class对象

public class SynchronizedStaticMethod {

    public static void main(String[] args) {

        //锁定当前Class对象
        SynchronizedStaticMethod.read();

    }

    public static synchronized void read() {
        System.out.println("I am SynchronizedStaticMethod");
    }
}

3.同步方法块,锁定synchronized 后括号中配置的对象(既可以是Class的实例对象也可以是Class对象)

public class SynchronizedCodeBlock {

    public void read(){
        //锁定当前实例对象
        synchronized(this){
            System.out.println("I am SynchronizedCodeBlock");
        }
        
        //锁定当前Class对象
        synchronized(SynchronizedCodeBlock.class){
            System.out.println("I am SynchronizedCodeBlock");
        }
    }
}

JAVA内存模型定义了8种操作来完成主内存和工作内存(线程独有),分别是lock(锁定)、unlock(解锁)、read(读取)、load(载入)、use(使用)、assign(赋值)、store(存储)、write(写入),其中lock和unlock可以实现代码块范围的原子性操作,虚拟机并未直接将lock和unlock操作直接开发给用户使用,但是提供了更高层次的字节码指令monitorenter和monitorexit来隐式使用这两个操作,而monitorenter和monitorexit即为synchronized的实现,因此在synchronized所保护的代码逻辑执行为原子性,当使用synchronized时会将monitorenter和monitorexit字节码分别插入到所保护的代码逻辑的开始和结束

我们使用javap反编译SynchronizedCodeBlock.class得到如下字节码

 public SynchronizedCodeBlock();
   Code:
      0: aload_0
      1: invokespecial #1                  // Method java/lang/Object."<init>":()V
      4: return

 public void read();
   Code:
      0: aload_0
      1: dup
      2: astore_1
      3: monitorenter  //在控制台输出之前插入monitorenter  指令
      4: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
      7: ldc           #3                  // String I am SynchronizedCodeBlock
      9: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     12: aload_1
     13: monitorexit   //当执行完逻辑退出 monitorexit   
     14: goto          22
     17: astore_2
     18: aload_1
     19: monitorexit
     ...............

在同一时刻只能有一个线程进入monitorenter直到将monitorexit 执行完成后,在由其他线程竞争进入,保证了同一时刻只有一个线程操作该资源以此实现原子性,并且修改过的共享变量是对其他线程立即可见,也就是实现可见性语义

总结

synchronized属于重量级锁,在保证线程安全的同时也需要付出性能损耗的代价,当然synchronized使用方便,安全性高也是它的优势,在java中还有Lock、CAS等实现线程同步,当然还有轻量级volatile关键字来保证线程安全,当然它们有各自的是用场景,如何选择可以根据具体是用场景来使用,当然只有理解了这些锁的机制,才能正确使用它们,并且能以最低的性能开销来保证线程安全

(转载请注明出处)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值