Moosphan/Android-Daily-Interview

2019-05-16:synchronized和volatile关键字的区别?

MoJieBlog opened this issue · 7 comments

2019-05-16:synchronized和volatile关键字的区别?

synchronized保证了程序执行的可见性和原子性;
volatile只保证了程序的可见性,禁止指令的重排序;

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
3.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
4.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

synchronized 可以保证原子性。他可以保证 在同一时刻,只有一个线程可以访问被 synchronized 修饰的方法,或者代码块。
volatile 不能保证原子性。当时在使用这个关键字后。当被Volatitle 修饰字段的值发生改变后,其他线程会立刻知道这个值已经发生变化了。volatitle 可以保证可见性和有序性。

打卡打卡

synchronized 可以保证原子性,可以用来进行线程同步,防止多线程出现的问题,可修饰 方法、类、代码块

volatile 不能保证原子性。我记得我在加解密网络请求的封装内见过,可以让其具有可见性,多线程操作时能发现olatitle 修饰字段的值变化

1、volatile不会进行加锁操作
volatile变量是一种稍弱的同步机制在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制。
2、volatile变量作用类似于同步变量读写操作
从内存可见性的角度看,写入volatile变量相当于退出同步代码块,而读取volatile变量相当于进入同步代码块。
3、volatile不如synchronized安全
在代码中如果过度依赖volatile变量来控制状态的可见性,通常会比使用锁的代码更脆弱,也更难以理解。仅当volatile变量能简化代码的实现以及对同步策略的验证时,才应该使用它。一般来说,用同步机制会更安全些。
4、volatile无法同时保证内存可见性和原子性
加锁机制(即同步机制)既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性,原因是声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。
当且仅当满足以下所有条件时,才应该使用volatile变量:
1、 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
2、该变量没有包含在具有其他变量的不变式中。
总结:在需要同步的时候,第一选择应该是synchronized关键字,这是最安全的方式,尝试其他任何方式都是有风险的。尤其在、jdK1.5之后,对synchronized同步机制做了很多优化,如:自适应的自旋锁、锁粗化、锁消除、轻量级锁等,使得它的性能明显有了很大的提升。

0、volatile的本质上是告诉JVM当前变量的值是不确定的,需要得到及时的更新,所以会把它放到工作内存当中,而synchronized会锁定该变量,只有当前线程可以访问,其他线程会被阻塞。volatile不会造成线程阻塞,synchronized则有可能会出现。

1、volatile在线程同步情况下,要比synchronized性能要好,但是volatile只能作用于变量上,而synchronized可以作用于方法或代码块

2、volatile可以保证变量的可见性,但不能保证原子性,而synchronized可以保证两者

3、volatile解决的是多个线程对变量的可见性,而synchronized解决的是多个线程之间访问资源的同步问题

volatile可以保证内存可见性、有序性(禁止指令重排);
synchronized可以保证内存可见性、原子性和互斥性(无禁止指令重排的作用哦);