volatile和synchronized的区别
- 原子性:不可分割,线程A在执行任务的时候,不能被打扰,也不能被分割,要么同时成功,要么同时失败。
- 指令重排: 是指在程序执行过程中,为了性能考虑,编译器和CPU可能会对指令重新排序。
- 可见性:简单来说就是一个线程修改了变量,其他线程可以立即知道。
synchronized工作原理:
- 进入 synchronized 块的内存语义是把在 synchronized 块内使用的变量从线程的工作内存中清除,从主内存中读取;
- 退出 synchronized 块的内存语义是把在 synchronized 块内对共享变量的修改刷新到主内存中。
volatile工作原理:
- 线程在【读取】共享变量时,会先清空工作内存变量值,再从主内存获取最新值;
- 线程在【写入】共享变量时,不会把值缓存在工作内存,而是会把值刷新回主内存。
- volatile 用于多线程环境下的单次操作(单次读或者单次写)。
总结
- volatile是变量修饰符,而synchronized则作用于一段代码或方法。
- volatile只是在线程内存和主内存间同步某个变量的值;而synchronized通过锁定和解锁某个监视器同步所有变量的值,显然synchronized要比volatile消耗更多资源。
- volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
- volatile保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存中和公共内存中的数据做同步。
volatile
关键字解决的是内存可见性的问题,会使得所有对volatile
变量的读写都会直接刷到主存,即保证了变量的可见性。使用volatile
关键字仅能实现对原始变量(如boolean、 short 、int 、long等)操作的原子性,但需要特别注意,volatile
不能保证复合操作的原子性,即使只是i
,实际上也是由多个原子操作组成:read i; inc; write i
,假如多个线程同时执行i
,volatile
只能保证他们操作的i
是同一块内存,但依然可能出现写入脏数据的情况。 - volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。