多线程

1 篇文章 0 订阅
1 篇文章 0 订阅

volatile关键字及其作用:


一. 保证内存可见性

**1基本概念

CREATE INDEX indexName ON mytable(username(length)); 

可见性是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果,另一个线程马上就能看到。
**2实现原理
当对非volatile变量进行读写的时候,每个线程先从主内存拷贝变量到cpu缓存中,如果计算机有多个CPU,每个线程可能在不同的cpu上被处理,这就意味着每个线程可以拷贝到不同的cpu cache中
volatile变量不会被缓存在寄存器或者其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过CPU cache 这一步。当一个线程修改了这个变量的值,新值对于其他线程是立即得知的
在这里插入图片描述

二.禁止指令重排

**1.基本概念
指令重排序是jvm为了优化指令,提高程序运行效率,在不影响单线程执行结果的前提下,尽可能的提高并行度。指令重排序包括编译器重排序和运行时重排序。
latile变量禁止指令重排序。针对volatile修饰的变量,在读写操作指令前后会插入内存屏障,指令重排序时不能把后面的指令重排序到内存屏障

示例说明:
double r = 2.1; //(1) 
double pi = 3.14;//(2) 
double area = pi*r*r;//(3) 

虽然代码语句的定义顺序为1->2->3,但是计算顺序1->2->3与2->1->3对结果并无影响,所以编译时和运行时可以根据需要对1、2语句进行重排序。

**指令重排带来的问题
如果一个操作不是原子的,就会给JVM留下重排的机会。

线程A中
{
    context = loadContext();
    inited = true;
}

线程B中
{
    if (inited) 
        fun(context);
}

如果线程A中的指令发生了重排序,那么B中很可能就会拿到一个尚未初始化或尚未初始化完成的context,从而引发程序错误。

三.适用场景

(1)volatile是轻量级同步机制。在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,是一种比synchronized关键字更轻量级的同步机制。

(2)volatile无法同时保证内存可见性和原子性。加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性

(3)volatile不能修饰写入操作依赖当前值的变量。声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。

(4)当要访问的变量已在synchronized代码块中,或者为常量时,没必要使用volatile;

(5)volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值