volatile关键字 学习记录2

 1 public class VolatileTest2 implements Runnable{
 2     volatile int resource = 0;
 3
 4     public static void main(String[] args) {
 5         VolatileTest2 vt = new VolatileTest2();
 6         new Thread(vt).start();
 7         new Thread(vt).start();
 8         while(Thread.activeCount() > 1){
 9             Thread.yield();
10         }
11         System.out.println(vt.resource);
12     }
13
14     @Override
15     public void run() {
16         for(int i=0; i<100000000; i++){
17             resource++;
18         }
19     }
20 }

这个例子中虽然resource前面有volatile关键字,但是运行结果有时候仍然不是200000000..为什么呢? 我想分享下我的观点.

首先每个线程有自己的内存,他们修改resource的时候会先把数据拷贝到自己的内存中,再修改,再写回主内存..所以如果是这样的话那么多个线程同时操作可能会有很多种情况,下面举2种情况

(不加volatile关键字的时候会出现的N种情况中的2种)

第一种情况:

第二种情况

上面2种情况都会使t2线程把resource写回主内存的时候把t1自增那次操作覆盖掉.因为t1与t2线程读主内存的resource的值是一样的...所以相当于t1的自增是无效的.

当resource前面加了volatile关键字的时候:

用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最新的值。

http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html

所以加了这个关键字以后是可以避免第二种情况的.

t1 resource自增以后会直接写回主内存,使t2读取操作读取到的是最新的值.相当于resource++与写回主内存是同一个事务,不可以分隔.

但是仍然不能避免第一种情况的发生.

在第一种情况下,线程t2 读取resource是发生在t1 resource自增之前的,所以当t1 自增以后并不会影响t2线程内存中的resource,因为这并不违背volatile.如果此时t2再去读取resource那才是最新的值.不过可惜他在t1自增之前就读取了,所以t2中resource的值仍然是旧的.当t2写回主内存的时候仍然会覆盖t1自增的值.

以上就是我的理解.

时间: 2024-10-07 03:01:12

volatile关键字 学习记录2的相关文章

volatile关键字 学习记录1

虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程..... 然后最近一直在看相关知识..所以就有了这篇文章 用例子来说明问题吧 1 public class VolatileTest { 2 boolean b = false; 3 int a = 0; 4 5 public static void main(String[] args) { 6 for (int i=0; i<1000000; i++) { 7 VolatileTest resource =

volatile关键字学习

特性一注意:只使变量在线程之间具有可见性,变量被修改值直接刷新主内存.但没有使变量具有原子性,多个线程修改值的时候任然会出错. 特性二注意:指令重:jvm会对指令进行优化,在单线程下不影响程序的结果,但是在多线程的情况下有可能会对程序的运行结果造成影响,volatile关键字可以避免这种影响. 原文地址:https://www.cnblogs.com/jinlin/p/8964706.html

java中volatile关键字

java中volatile关键字 学习ImageLoader源码时遇到遇到这么一个关键字,以前没遇到过,也不明白是何含义,网上找了部分资料,总结记录一下. 在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉.Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来

JAVA多线程基础学习三:volatile关键字

Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个关键字的作用就是告诉编译器,只要是被此关键字修饰的变量都是易变的.不稳定的.那为什么是易变的呢?因为volatile所修饰的变量是直接存在于主内存中的,线程对变量的操作也是直接反映在主内存中,所以说其是易变的. 一.Java内存模型 Java内存模型规定所有的变量都是存在主存当中(类似于前面说的物理

C语言学习笔记--const 和 volatile关键字

1.const关键字 (1)const 修饰的变量是只读的,它不是真正的常量,本质还是变量,只是告诉编译器不能出现在赋值号左边! (2)const 修饰的局部变量在栈上分配空间 (3)const 修饰的全局变量在全局数据区分配空间(vc.gcc 会将其放入常量区,bcc 放入全局数据区) (4) const 只在编译期有用,在运行期无用 #include <stdio.h> const int g_cc = 2;//bcc 下存储在全局数据区,可修改. //vc.gcc 将其存储在常量区,不可

Thread 学习记录 &lt;1&gt; -- volatile和synchronized

恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1;              int geti1() {return i1;} volatile int i2;  int geti2() {return i2;} int i3;              synchronized int geti3() {return i3;} geti1()得到存

Java设计模式学习记录-单例模式

前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 单例模式的实现方式 实现单例模式的方式有很多种,大体上可以划分为如下两种. 外部方式 在使用某些全局对象时,做一些“try-Use”的工作.就是如果要使用的这个全局对象不存在,就自己创建一个,把它放到全局的位置上:如果本来就有,则直接拿来使用. 内部实现方式 类型自己控制正常实例的数量,无论客户程序

Python学习记录day1

Python学习记录博客是本人记录学习python3过程中的一些记录和过程,日后也可以帮助自己温习. python优点: 1.Python入门简单,功能强大,适用性强: 2.开发效率高,第三方库强大且多: 3.Python无需考虑底层细节: 4.可移植性,跨平台: 5.可扩展性: 6.可嵌入性,Pthon可嵌入到C/C++程序中: python缺点: 1.速度慢,Python比C慢很多,比java也慢一点: 2.代码不能加密,源码是明文: 3.线程不能利用多 CPU 问题: python版本2和

【学习记录】关于makefile而进行的互联网学习技巧练习及学习笔记和学习心得记录(vs2010)

我也不知道作为一个完全的windows平台下的不怎么专业的软件工程学生,看到<Accelerated C++>的源代码,第一反应是:哦!我应该用make生成工程文件.然后我愉快的用AOL开始搜索相关资料. 然并卵!我一定是被什么奇怪的生物附身了.我应该直接用vs创建项目->导入文件.然后……ctrl+F5.多么完美. 可是……以下: [教程]来自于云风大大的blog(云风的 BLOG) IDE 不是程序员的唯一选择(一) 以及后面的(二)(三)(四) 以及大大写了一篇半,只为了说明用cl