面试必问的Volatile实例解析

1.Volatile是否保证原子性

package charter2;

/**
 * @Auther: 洺润Star
 * @Date: 2020/4/11 11:30
 * @Description:测试Volatile是否能保证原子性
 */
public class TesetVolatileAtomicity {
    public static volatile int cnt =0;

    public static void add(){
        //延迟1毫秒,增加多线程并发抢占的概率。
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        cnt++;
    }

    public static void main(String[] args) {
        for (int i=0;i<1000;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    TesetVolatileAtomicity.add();
                }
            }).start();
        }
        //每次运行结果都有可能不同
        System.out.println(TesetVolatileAtomicity.cnt);//267
    }

}

通过代码创建1000个线程进行++操作,可以看到结果是一定是小于1000的,毫无疑问Volatile不能保证原子性。

2. Volatile特性一:禁止重排序

多线程环境下重排序会造成意想不到的结果,而如果对变量添加Volatile进行修饰则可禁止重排序优化,从而防止重排序对多线程的影响。
在单线程程序中,对存在控制依赖的操作重排序,不会改变执行结果(这也是as-if-serial语义允许对存在控制依赖的操作做重排序的原因);但在多线程程序中,对存在控制依赖的操作重排序,可能会改变程序的执行结果。

3. Volatile特性二:保证线程间可见

• 对线程内存变量的写操作,能立即写回主内存
在这里插入图片描述
• 能实现并发的HashMap也就是ConcurrentHashMap,其中定义了map的长度

private transient volatile long baseCount;

存储该对象长度的变量是volatile
多个线程同时读写该ConcurrentHashMap对象,对长度的修改能立即让其它线程感知

线程可见性举例:

package charter2;

/**
 * @Auther: 洺润Star
 * @Date: 2020/4/11 11:16
 * @Description:测试VolatileForVisible 主线程变量的修改不能影响线程变量
 */
public class TestVolatileForVisible extends Thread{

    boolean stopFlag = false;
    public int cnt = 0;

    @Override
    public void run() {
        while (!stopFlag){
            cnt++;
        }
        System.out.println("我终止了");

    }

    public static void main(String[] args) throws InterruptedException {
        TestVolatileForVisible testVolatileForVisible = new TestVolatileForVisible();
        testVolatileForVisible.start();
        Thread.sleep(5000);
        testVolatileForVisible.stopFlag = true;
        System.out.println(testVolatileForVisible.cnt);
    }
}

代码中在不添加volatile的情况下虽然说也会输出cnt值的大小,但是程序不会停止。
因为虽然将stopFlag设为了true但由于线程不可见性run方法所在的线程stopFlag值仍未false并没有及时更新 所以线程不会停止

volatile boolean stopFlag = false;

添加volatile后,stopFlag 会及时加载到主内存中,所有线程内存中stopFlag值 将会一致,所以线程将会被停止掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值