【JVM】synchronized为什么具有可见性,原子性,有序性?

6 篇文章 0 订阅

对于为什么volatile具有:“有可见性,有序性,但没有原子性”,可以看我的另一篇博客:https://blog.csdn.net/qq_35590091/article/details/106986536

synchronized是互斥同步的手段的一种,主要用来解决多个线程并发访问共享数据时,保护数据的一致性的问题。  


原子性

     synchronized经过编译之后,对应的是class文件中的monitorenter和monitorexit这两个字节码指令。这两个字节码对应的内存模型的操作是lock(上锁)unlock(解锁)。因为这两个操作之间运行的都是原子的(这个操作保证了变量为一个线程独占的,也就是说只有获得锁的线程才能够操作被锁定的内存区域),所以synchronized也具有原子性

  这两个字节码都需要一个对象来作为锁。因此,

1、如果synchronized修饰的是实例方法,则会传入this作为参数,

2、如果修饰的是静态方法,则会传入class类对象作为参数。

3、如果只是一个同步块,那么锁就是括号里配置的对象。

执行monitorenter字节码时,如果这个对象没有被上锁,或者当前线程已经持有了该锁,那么锁的计数器会+1,而在执行monitorexit字节码时,锁的计数器会-1,当计数器为0时,锁被释放。如果获取对象的锁失败,那么该线程会被阻塞等待,直到之前把这个对象上锁的线程释放这个锁为止。

每个对象都有一个monitor(监视器)与之关联,所谓的上锁,就是获得对象的monitor的独占权(因为只用获得monitor才能访问这个对象)。执行monitorenter字节码的时候,线程就会尝试获得monitor的所有权,也就是尝试获得对象的锁。只有获得了monitor,才能进入同步块,或者执行同步方法。独占对象的本质是独占对象的monitor。


可见性

 此外,synchronized也具有可见性,因为它调用的unlock解锁这个操作规定,放开对某个变量的锁的之前,需要把这个变量从缓存更新到主内存,因此它也具有可见性


有序性

 为什么synchronized无法禁止指令重排,却能保证有序性??因为在一个线程内部,他不管怎么指令重排,他都是as if serial的,也就是说单线程即使重排序之后的运行结果和串行运行的结果是一样的,是类似串行的语义。而当线程运行到同步块时,会加锁,其他线程无法获得锁,也就是说此时同步块内的方法是单线程的,根据as if serial,可以认为他是有序的。而指令重排序导致线程不安全是多线程运行的时候,不是单线程运行的时候,因此多线程运行时静止指令重排序也可以实现有序性,这就是volatile。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值