从头认识多线程-3.2 使用volatile声明的变量的写操作是非原子性的

这一章节我们来讨论一下使用volatile声明的变量的各种操作是非原子性的。

1.上一章节我们已经提到,volatile把工作内存里面变量的改变同步到主内存, 使得各个线程能够把该变量当成是整体的状态控制

2.但是,使用volatile声明的变量的写操作是非原子性的

代码清单:

package com.ray.deepintothread.ch03.topic_2;

public class VolatileTest extends Thread {

	private volatile int id = 0;

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("Thread name :" + Thread.currentThread().getName() + " id :" + id++);
			try {
				sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) throws InterruptedException {
		VolatileTest volatileTest1 = new VolatileTest();
		VolatileTest volatileTest2 = new VolatileTest();
		volatileTest1.start();
		Thread.sleep(100);
		volatileTest2.start();
	}
}

输出:

Thread name :Thread-0 id :0
Thread name :Thread-0 id :1
Thread name :Thread-1 id :0
Thread name :Thread-0 id :2
Thread name :Thread-1 id :1
Thread name :Thread-0 id :3
Thread name :Thread-1 id :2
Thread name :Thread-0 id :4
Thread name :Thread-1 id :3
Thread name :Thread-0 id :5
Thread name :Thread-1 id :4
Thread name :Thread-0 id :6
Thread name :Thread-1 id :5
Thread name :Thread-0 id :7
Thread name :Thread-1 id :6
Thread name :Thread-0 id :8
Thread name :Thread-1 id :7
Thread name :Thread-0 id :9
Thread name :Thread-1 id :8
Thread name :Thread-1 id :9

从输出结果可以看出,id的读写操作是不同步的。

3.jvm的内存交互

注:本图摘自java中volatile关键字的含义

从图上面我们可以看见,id++操作等同于id=0,tmp=id+1,id=tmp的过程,这个过程是不同步的,在多线程状态下面,多次的赋值和写内存不在同步方法上面,数据没有保证一致性,因此,会出现上面的不同步的现象。

总结:这一章节主要讨论了使用volatile声明的变量的写操作是非原子性的。

这一章节就到这里,谢谢

------------------------------------------------------------------------------------

我的github:https://github.com/raylee2015/DeepIntoThread

目录:http://blog.csdn.net/raylee2007/article/details/51204573

时间: 2024-11-07 10:04:37

从头认识多线程-3.2 使用volatile声明的变量的写操作是非原子性的的相关文章

从头认识多线程-3.1 使用volatile解决异步死循环

这一章节我们来讨论一下使用volatile解决异步死循环. 1.在讨论上面的问题前,我们引入另一个例子:同步死循环 代码清单: package com.ray.deepintothread.ch03.topic_1; public class DeadFor { private boolean isStop = false; public boolean isStop() { return isStop; } public void setStop(boolean isStop) { this.

Java多线程(三)volatile域

相关文章 Java多线程(一)线程定义.状态和属性 Java多线程(二)同步 Android多线程(一)线程池 Android多线程(二)AsyncTask源码分析 前言 有时仅仅为了读写一个或者两个实例域就使用同步的话,显得开销过大,volatile关键字为实例域的同步访问提供了免锁的机制.如果声明一个域为volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的.再讲到volatile关键字之前我们需要了解一下内存模型的相关概念以及并发编程中的三个特性:原子性,可见性和有序性

从头认识多线程-2.8 缓解同步方法的隐患-同步代码块

这一章节我们来讨论一下缓解同步方法的隐患-同步代码块. 1.思路:把同步方法,降低同步的粒度,同步到代码块 2.根据上一章节的例子,我们把代码修改一下 (1)第一种方法,把同步标记移到更新的那一栏里面去,一般来说大部分都是更新的时候需要同步数据 package com.ray.deepintothread.ch02.topic_9; /** * 从头认识多线程-2.8 缓解同步方法的隐患-同步代码块<br> * * @author RayLee * */ public class Relief

多线程同步synchornized、volatile、Atomic、CountDownLatch示例

synchronized关键字 锁对象.synchronized(this)和synchronized方法都是锁当前对象. import java.util.concurrent.TimeUnit; public class Test_01 { private int count = 0; private Object o = new Object(); public static void main(String[] args) { final Test_01 t = new Test_01(

测试利用多线程进行文件的写操作

最近学习NIO技术,了解了有关channel通道.buffer缓存以及selector选择器等技术,萌发了想写一个多点下载的一个简单测试demo.我将这个demo分成两步,第一步先实现将一个文件分段复制到一个文件中(通常我们是将文件以流的形式一个字节一个字节的复制到目标文件中,现在我们是将文件分段,启用多个线程,每个线程复制一部分,然后再根据原文件分段的位置组装成一个文件,实现高效的目的).下面帖源码 /** * 测试利用多线程进行文件的写操作 * @author gcl * @version

Linux程序设计学习笔记----多线程编程之线程同步之条件变量

转载请注明出处:http://blog.csdn.net/suool/article/details/38582521. 基本概念与原理 互斥锁能够解决资源的互斥访问,但是在某些情况下,互斥并不能解决问题,比如两个线程需 要互斥的处理各自的操作,但是一个线程的操作仅仅存在一种条件成立的情况下执行,一旦错过不可再重现,由于线程间相互争夺cpu资源,因此在条件成立的时候,该线程不一定争夺到cpu而错过,导致永远得不到执行..... 因此需要某个机制来解决此问题,更重要的是,线程仅仅只有一种情况需要执

javascript中的函数式声明与变量式声明

观察下面两段代码,试写出hello('word');的运行结果: // 变量式声明 function hello(msg){ alert(msg); var msg = function(){}; alert(msg); } //函数式声明 function hello(msg){ alert(msg); function msg (){}; alert(msg); } 对于变量式声明,首先弹出word,然后弹出function,而函数式声明,则两次都是弹出function.这是为什么呢? 一:

sqlserver 必须声明标量变量 &quot;@id&quot; 什么原因,如何解决 存储过程 带参数

sqlserver 必须声明标量变量 "@id". 原因 set @sql = 'insert into stu(id,name) select top @id from stus'  // 错误 解决办法 set @sql = 'insert into stu(id,name) select top '+CONVERT(char(3),@id) +'from stus'  //正确

javascript中函数声明、变量声明以及变量赋值之间的关系与影响

函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 3.变量声明被提升到范围作用域的顶端 4.变量声明比函数声明的优先级高,变量声明优先于函数声明被提升,如果两者同名同时存在,后被提升的函数声明会覆盖先被提升的变量声明 5.变量赋值不会被提升,到执行行代码才开始赋值 补充: 6.调用javascript函数的整个过程可以分为预编译期(也叫声明期)和赋值期(也叫计算执行期). 预编译期完成对所有变量(包括形参.函数内部