2015年3月11日
来源:互联网 发布:做动画用什么软件 编辑:程序博客网 时间:2024/05/01 08:12
Atomic 类概述
java为什么会引入Atomic类的包呢?atomic类在java.util.concurrent包下面,可以知晓,该类的出现是与安全相关的,当我们对一个int类型的变量进行操作的时候,有可能会遇到线程安全的问题,我们可以先看一个用例,笔者自己并没能实验出来,该用例来源于文章,http://blog.csdn.net/a19881029/article/details/8202933
public class SCounter {private static int count;public void add() {System.out.println(Thread.currentThread().getName() + ":" + (count++));}public static void main(String[] args) {final SCounter sc = new SCounter();Runnable task1 = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubsc.add();}};ExecutorService es = Executors.newCachedThreadPool();for (int i = 0; i < 5; i++) {es.submit(task1);}es.shutdown();}}
其运行结果为:
pool-1-thread-2:0pool-1-thread-5:3pool-1-thread-1:2pool-1-thread-3:1pool-1-thread-4:4
偶尔会有:
pool-1-thread-2:0pool-1-thread-5:3pool-1-thread-1:2pool-1-thread-3:1pool-1-thread-4:3
位什么会有这个情况发生呢?
是因为其中我们在执行代码count++的时候,虽然只有一句代码,但是jvm确分成了几个步骤来完成这一操作。
getstatic 获取指定类的静态域,并将其值压入栈顶 iconst_1 将int型1推送至栈顶 iadd 将栈顶两int型数值相加并将结果压入栈顶 dup 复制栈顶数值并将复制值压入栈顶 putstatic 为指定类的静态域赋值
如果在有个线程在执行这5个步骤的过程中被打断了,那么就会出现上述安全问题。
2,atomic类的工作原理。
而atomic包里面提供了对一些基本类型的封装类比如说AtomicInteger,AtomicLong 等等,提供了一些机制,来确保最后被修改的值的安全性。
那么Atomic类是如何来确保其最后修改的值的正确性呢?在处理该问题之前,我们需要分清3个变量的值,expectValue---我们所期望我们的更改基于该值的。ActuralValue--实际当前内存地址上的值,newValue我们期望的更改之后新的值
拿atomicInteger的getAndSet方法来举例,其源码为:
public final int getAndSet(int newValue) { for (;;) { int current = get(); if (compareAndSet(current, newValue)) return current; } }
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
Unsafe的对象中compareAndSwapInt方法:
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset, jint expect, jint update) { jint *addr = (jint *)((char *)obj + offset); return compareAndSwap (addr, expect, update); }
compareAndSwap (volatile jint *addr, jint old, jint new_val) { jboolean result = false; spinlock lock; if ((result = (*addr == old))) *addr = new_val; return result; }
可以看见,atomicInteger 的getAndSet方法里面有一个for循环,该循环会不断的尝试和确认,我们当前的操作是否基于内存中最新的值,如果不是的话,就重新从内存中读取该值,并且把我们的需要更改的值添加上去。
从而来确保,无论任何时候,对于Integer的操作,都是正确的。
0 0
- 2015年3月11日工作总结
- 2015年3月11日
- 2014年12月30日,31日,2015年1月3日,4日
- 3月11日
- 11月3日
- 2015年11月3日技术日志的开篇
- 2015年2月11日
- 2015年7月11日UITableView3
- 2015年7月11日-FW
- 2015年9月11日
- 2015年11月5日小记
- 2015年11月6日
- 2015年11月8日 开篇
- 2015年11月9日杂谈
- 2015年11月12日
- 2015年11月13日
- 2015年11月14日
- 2015年11月16日
- 三种图片截图方法
- sitemesh的使用
- 数据库操作--保持连接间隔
- C++内存管理详解
- 头文件相关函数
- 2015年3月11日
- 为什么要有Unit Test
- 解决安装Laravel时的错误(ubuntu)
- [省选前题目整理][POJ 1830]开关问题(XOR方程组高斯消元)
- web服务器基本原理以及micro_httpd
- 比较Backbone.js, Angular.js, Ember.js, Knockout.js
- Android圆角、点击背景----shape和selector和layer-list使用
- 辛星浅析Linux中的GCC
- 有关智能操作系统的讨论