【JAVA】volatile和synchronized的区别

JAVA 同时被 2 个专栏收录
145 篇文章 19 订阅
30 篇文章 3 订阅

共性:

volatile与synchronized都用于保证多线程中数据的安全

区别:

(1)volatile修饰的变量,jvm每次都从主存(主内存)中读取,而不会从寄存器(工作内存)中读取。

而synchronized则是锁住当前变量,同一时刻只有一个线程能够访问当前变量

(2)volatile仅能用在变量级别,而synchronized可用在变量和方法中

(3)volatie仅能实现变量的修改可见性,无法保证变量操作的原子性。而synchronized可以实现变量的修改可见性与原子性


【1】可见性

说的是一个线程如果更改了某个变量的值,其他线程能够立刻知道这个变量更改后的值

【2】原子性

一个操作要么全做,要么全不做,就像不可分割的原子一样。银行转账这个操作必须具有原子性,A转账给B1000元,A账户减去1000元,B账户加上1000元,两个操作不可分割,不可单独出现,否则会出现意料之外的结果。


例:volatile int  i=0;并且大量线程调用i的自增操作,那么volatile可以保证变量的安全吗?

不可以保证,volatile不能保证变量操作的原子性,自增操作包括三个步骤,分别是读取,加一,写入,由于这三个子操作的原子性不能被保证,那么n个线程总共调用n次i++的操作后,最后的i的值并不是大家想的n,而是一个比n小的数

解释:比如A线程执行自增操作,刚读取到i的初始值0,然后就被阻塞了

B线程现在开始执行,还是读取到i的初始值0,执行自增操作,此时i的值为1

然后A线程阻塞结束,对刚才拿到的0执行加一与写入操作,执行成功后,i的值被写成1了,

我们预期输出2,可是输出的是1,输出比预期小。

代码验证

package day0807;

import java.util.ArrayList;
import java.util.List;

public class VolatileTest {
    public volatile int i = 0;

    public void increase() {
        i++;
    }

    public static void main(String args[]) throws InterruptedException {
        List<Thread> threadList = new ArrayList<>();
        VolatileTest test = new VolatileTest();
        for (int j = 0; j < 10000; j++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    test.increase();
                }
            });
            thread.start();
            threadList.add(thread);
        }

        //等待所有线程执行完毕
        for (Thread thread : threadList) {
            thread.join();
        }
        System.out.print(test.i);
    }
}

输出为

(4)volatile不需要加锁,因此不会造成线程的阻塞,而且比synchronized更轻量级,而synchronized可能导致线程的阻塞

  • 6
    点赞
  • 0
    评论
  • 23
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值