volatile关键字

1.volatile关键字: 当把JVM设置为Server服务器的环境中,线程会从自己的私有堆栈中读取变量值。这时如果其他线程更改了该变量,只是更改了公共堆栈,并没有更改另一条线程的私有堆栈。这样就容易造成死循环状态。

image.png

这个问题其实就是私有堆栈中的值和公共堆栈中的值不同步造成的。解决这样的问题就要使用volatile关键字了,它的主要作用就是当线程访问变量时,强制性从公共堆栈中进行取值。

image.png

volatile和synchronized的比较:

1)关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法,以及代码块。随着JDK新版本的发布,synchronized关键字在执行效率上得到很大提升,在开发中使用synchronized关键字的比率还是比较大的。

2)多线程访问volatile不会发生阻塞,而synchronized会出阻塞。

3)volatile能保证数据可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据同步。

关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么也就不具备原子性。

public class MyThread extends Thread{
    volatile public static int count;
    private static void addCount(){
    for(int i = 0;i<100;i++){
          count++;
      }
      System.out.println("count=" + count);
    }
    @Override
    public void run(){
        addCount();
    }
}
public static void main(String[] args){
    MyThread[] mythreadArray = new MyThread[100];
    for(int i = 0;i<100;i++){
        mythreadArray[i] = new MyThread();
    }
    for(int i = 0;i<100;i++){
        mythreadArray[i].start();
    }
}
public class MyThread extends Thread{
    volatile public static int count;
    //注意一定要添加static关键字
    //这样synchronized与static锁的内容就是MyThread.class类了
    //也就达到同步效果
    synchronized private static void addCount(){
    for(int i = 0;i<100;i++){
          count++;
      }
      System.out.println("count=" + count);
    }
    @Override
    public void run(){
        addCount();
    }
}

4)再次重申,关键字解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。

线程安全包含原子性和可见性两个方面,Java的同步机制都是围绕这两个方面来确保线程安全的。

但是volatile关键字最致命的缺点就是不支持原子性:关键字volatile虽然增加了实例变量在多个线程之间的可见性,但它却不具备同步性,那么不具备原子性。关键字volatile主要使用的场合是在多个线程中可以感知实例变量被更改了,并且可以获得最新的值使用,也就是用多线程读取共享变量时可以获得最新值使用。
关键字volatile提示线程每次从共享内存中读取变量而不是从私有内存中读取,这样就保证了同步数据的可见性。但在这里需要注意的是:如果修改实例变量中的数据,比如i++,也就是i=i+1,则这样的操作其实并不是一个原子操作,也就是非线程安全的。表达式i++的操作步骤分解如下:
1)从内存中取出i的值。
2)计算i的值。
3)将i的值写到内存中。
假如在第2步计算值的时候,另外一个线程也修改i的值,那么这个时候就会出现脏数据。解决的办法其实就是使用synchronized关键字。所以说volatile本身并不处理数据的原子性,而是强制对数据的读写及时影响到主内存的。

1)read和load阶段:从主内存复制变量到当前线程工作内存;
2)use和assign阶段:执行代码,改变共享变量值;
3)store和write阶段:用工作内存数据刷新主内存对应变量的值。

image.png

多线程环境中,use和assign是多次出现的,但这一操作并不是原子性,也就是在read和load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应变化,也就是私有内存和公共内存中的变量不同步,所以计算出来的结果会和预期的不一样,也就出现了非线程安全问题。
对于volatile修饰的变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新的,例如线程1和线程2在进行read和load的操作中,发现主内存中count的值都是5,那么都加载这个最新的值。也就是说,volatile关键字解决的是变量读时的可见性问题,但无法保证原子性,对于多个线程访问一个实例变量还是需要加锁同步。

2.原子类: 除了在i++操作时使用synchronized关键字实现同步之外,还可以使用AtomicInteger原子类进行实现。
原子操作是不能分割的整体,没有其他线程能够中断或检查正在原子操作中的变量。一个原子类型就是一个原子操作可用的类型,它在没有锁的情况下做到线程安全。
但是原子类的方法和方法之间的调用却不是原子的,这样可以加synchronized关键字来同步不同的addAndGet()方法。

3.synchronized代码块有volatile同步功能:关键字synchronized可以使多个线程访问同一个资源具有同步性,而且它还具有将线程工作内存中的私有变量与公共内存中的变量同步功能。关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或某一个代码块。它包含两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由一个锁保护之前所有的修改效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • volatile 关键字解析 原文出处: 海子volatile 这个关键字可能很多朋友都听说过,或许也都用过。在 ...
    常青大侠阅读 579评论 0 4
  • 此文章出自:<a href="http://www.cnblogs.com/dolphin0520/p/39203...
    zlb阅读 624评论 0 6
  • 偶听朋友提到其母和其弟的事情,觉着逗乐,遂记之。 其弟在小学的时候就已颇高颇壮。某日犯错,其母抬手欲训之。其弟公主...
    阴阴阅读 335评论 0 0
  • 01 昨天,刚好看到孩子在窗外的坪里熟练、姿势优美地跳绳的情形,于是一句话就那样蹦出我的脑海:熟能生巧,有种爱就叫...
    西瓜甜甜啦阅读 656评论 18 36
  • 昨天晚上,他在吃饭的时候不断地和我说明年,未来三到五年的计划,引用当红经济学家的话语,数据分析,逻辑性极强,而我却...
    bef243e45c7f阅读 218评论 0 2