多线程里的关键字听说了吗? Volatile vs Synchronized

本文探讨了Java多线程中Volatile和Synchronized的区别与应用场景。Volatile仅保证内存可见性和有序性,但不保证原子性,适用于有限场景。而Synchronized则提供原子性、可见性和有序性,确保线程安全,可能导致线程阻塞。两者的使用层级和优化程度也有所不同。
摘要由CSDN通过智能技术生成

Volatile
只能保证操作的内存可见性和有序性,不能保证对变量的操作是原子性的。
作用
非常局限的场景下,可以保证原子性
保证变量的内存可见性,被Volatile修饰的变量,每次读,必须从主内存同步;每次写,必须附带写回主内存 (最重要的作用-90%)
非常局限的场景下,可以保护代码重排引起的问题

在这里插入图片描述

Synchronized :
可以保证原子性、可见性和有序性。每个 Java 对象都有一个关联的 monitor,使用synchronized 时 JVM 会根据使用环境找到对象的 monitor,根据 monitor 的状态进行加解锁的判断。如果成功加锁就成为该 monitor 的唯一持有者,monitor 在被释放前不能再被其他线程获取。

在这里插入图片描述

Java语法:
修饰方法,用在普通方法或者静态方法之前

public synchronized void method() {
     
    }
public static synchronized void staticMethod() {
          
    }
   2. 同步代码块
public void someMethod() {
        // 同步代码块,用在方法内部
        Object o = new Object();
        synchronized (o) {
            // o 这个引用不能是 null
        }
    }

在这里插入图片描述

Synchronized是如何实现加锁的 - 以同步代码块为例

如果Sync加锁失败,会怎么办?
加锁失败,之后就没有资格继续执行代码了
占据CPU没有意义了
会触发线程调度 ,加锁失败的线程,会被调度器从CPU调度下来
在锁打开之前,再分配CPU给该线程也没有意义
线程状态要变化(不再是Runnable(ready/running))
线程状态变成Blocked(sync加锁失败专用状态)
当准备好了释放锁时,可以找到该线程,把它叫回来
把线程加到这把锁的阻塞队列中(Blocking queue)

Volatile 和 Synchronized 的区别
Volatile本质是告诉JVM当前寄存器(工作内存)中的值是不确定的,需要从主内存中读取;Syn则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞。
volatile 仅能使用在变量级别;synchronized 则可以使用在变量、方法、和类级别的。
volatile 仅能实现变量的修改可见性,不能保证原子性;而 synchronized 则可以保证变量的修改可见性和原子性
volatile 不会造成线程的阻塞;synchronized 可能会造成线程的阻塞(多个线程争抢synchronized 锁对象时,会出现阻塞)
volatile 标记的变量不会被编译器优化;synchronized 标记的变量可以被编译器优化。
仅仅使用 volatile 并不能保证线程安全性。而 synchronized 则可实现线程的安全性。因为线程安全取决于原子性和可见性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值