AtomicInteger关键字
validate 关键字可以保证多线程之间的可见性,但是不能保证原子操作。(需要了解java内存模型jmm)
package com.cn.test.thread;
public class VolatileAutomic extends Thread{
private volatile static int count = 0;
public static void add() {
for (int i = 0; i < 10000; i++) {
count ++;
}
}
@Override
public void run() {
add();
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new VolatileAutomic().start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
// System.out.println(atomicCount.get());
System.out.println("count=" + count);
}
}
运行结果:
count=61618
上面例子中volatile关键字能保证可见性没有错,但是上面的程序错在没能保证原子性。可见性只能保证每次读取的是最新的值,但是volatile没办法保证对变量的操作的原子性。
count++是一个非原子性的操作,它包括读取变量的原始值、进行加1操作、写入工作内存。那么就是说自增操作的三个子操作可能会分割开执行,就有可能导致的情况:
假如某个时刻变量count的值为10,线程1对变量进行自增操作,线程1先读取了变量count的原始值,然后线程1被阻塞了;线程2也对变量进行自增操作,线程2先读取了count的原始值,线程1只是进行了读取操作,没有进行写的操作,所以不会导致线程2中的本地缓存无效,因此线程2进行++操作,在把结果刷新到主存中去,此时线程1在还是读取原来的10 的值在进行++操作,所以线程1和线程2对于count=10进行两次++操作,结果都为11.。
上述问题解决方法:
1.采用add方法中加入sychnorized.,或者同步代码块
2.采用AtomicInteger
package com.cn.test.thread;
import java.util.concurrent.atomic.AtomicInteger;
public class VolatileAutomic extends Thread{
static AtomicInteger atomicCount = new AtomicInteger(0);
public static void add() {
for (int i = 0; i < 10000; i++) {
atomicCount.incrementAndGet();
}
}
@Override
public void run() {
add();
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new VolatileAutomic().start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(atomicCount.get());
}
}
运行结果:
100000
AtomicInteger是java.util.concurrent.atomic并发包下面一个类。
AtomicInteger源码理解:
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
/**
* Creates a new AtomicInteger with the given initial value.
*
* @param initialValue the initial value
*/
public AtomicInteger(int initialValue) {
value = initialValue;
}
调用AtomicInteger的构造方法传入一个initialValue值,将initialValue复制给一个volatile 的value,
/**
* Atomically increments by one the current value.
*
* @return the updated value
*/
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while (!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
底层源码实现主要采用cas算法的思想,通过操作底层硬件的指令。cas锁是一种无锁的机制。cas的机制:v的值应该是A,如果是A则将值更新为B。当多个线程同时要更新V的值,
只有其中一个线程更新成功,其他线程更新失败,更新失败的线程并不会挂起,而是在继续进行竞争资源,对V的值进行操作。
cas锁的机制采用的是事物提交-- 失败--重试来保证原子性。
cas锁的缺点:当并发量大的时候,多线程一直进行重试,这样会导致CPU的开销很大。
package com.cn.test.thread; import java.util.concurrent.atomic.AtomicInteger; /**
* 设计4个线程,其中两个线程 每次对j增加1,另外两个线程对j每次减少1。写出程序。
*
*/
public class TestAtomicThread extends Thread {
private static int j = 10;
static AtomicInteger atomicInteger = new AtomicInteger(j);
public TestAtomicThread(String string) {
super(string);
} @Override
public void run() {
System.out.println(Thread.currentThread().getName());
switch(Thread.currentThread().getName()) {
case "thread-1":
case "threa-2":
atomicInteger.incrementAndGet();
// System.out.println("当前线程名称:" + Thread.currentThread().getName() + ":" + atomicInteger.get());
break;
case "thread-3":
case "thread-4": atomicInteger.decrementAndGet();
// System.out.println("当前线程名称:" + Thread.currentThread().getName() + ":" + atomicInteger.get());
break;
default : break;
}
} public static void main(String[] args) {
TestAtomicThread t1 = new TestAtomicThread("thread-1");
TestAtomicThread t2 = new TestAtomicThread("thread-2");
TestAtomicThread t3 = new TestAtomicThread("thread-3");
TestAtomicThread t4 = new TestAtomicThread("thread-4");
t1.start();
t2.start();
t3.start();
t4.start();
if (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println("j====" + atomicInteger.get()); } }
AtomicInteger关键字的更多相关文章
- 作为一个新手的Oracle(DBA)学习笔记【转】
一.Oracle的使用 1).启动 *DQL:数据查询语言 *DML:数据操作语言 *DDL:数据定义语言 DCL:数据控制语言 TPL:事务处理语言 CCL:指针控制语言 1.登录 Win+R—cm ...
- java IO操作和计算操作:工作内存和主内存 volatile关键字作用;原子操作对象AtomicInteger ....
应该停止但无法停止的计算线程 如下线程示例,线程实例中while循环中的条件,在主线程中通过调用实例方法更新后,while循环并没有更新判断变量是否还成立.而是陷入了while(true)死循环. i ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- java中关键字volatile的作用
用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...
- 【转】Java并发编程:volatile关键字解析
转自:http://www.importnew.com/18126.html#comment-487304 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备 ...
- 架构师养成记--4.volatile关键字
volatile修饰的变量可在多个线程间可见. 如下代码,在子线程运行期间主线程修改属性值并不对子线程产生影响,原因是子线程有自己独立的内存空间,其中有主内存中的变量副本. public class ...
- zz剖析为什么在多核多线程程序中要慎用volatile关键字?
[摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...
- Java多线程6:synchronized锁定类方法、volatile关键字及其他
同步静态方法 synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁.看一下例子,注意一下printC()并不是一个静态方法: public ...
- java并发:线程同步机制之Volatile关键字&原子操作Atomic
volatile关键字 volatile是一个特殊的修饰符,只有成员变量才能使用它,与Synchronized及ReentrantLock等提供的互斥相比,Synchronized保证了Synchro ...
随机推荐
- “全栈2019”Java第三十章:数组详解(下篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- oracle无监听程序的解决方法(PLSQL)Oracle ORA12514 监听程序当前无法识别连接描述符中请求的服务
\PLSQL\instantclient_11_2 listener.ora # listener.ora Network Configuration File: E:\software\PLSQL\ ...
- 队列优化dijsktra(SPFA)的玄学优化
转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2 优化 对一些数 ...
- 2016级算法第四次上机-E.Bamboo and the Ancient Spell
Bamboo and the Ancient Spell 分析 可能英文读题难度比较大,但是只要看到全大写的 "THE LONGEST COMMON SUBSEQUENCE !"应 ...
- 「DB」数据库事务的隔离级别
*博客搬家:初版发布于 2017/04/10 00:37 原博客地址:https://my.oschina.net/sunqinwen/blog/875833 数据库事务的隔离级别 讲事务的隔离 ...
- 持续集成、持续交付、持续部署、Jkens、git
一 持续集成.持续交付.持续部署 1. 持续集成 持续集成指的是,频繁地(一天多次)将代码集成到主干.持续集成的目的,就是让产品可以快速迭代,同时还能 保持高质量.它的核心措施是,代码集成到主干之前 ...
- 分分钟钟学会Python - 数据类型(int、bool、str)
第三天学习内容 今日内容 1.整型(int) 2.布尔类型(bool) 3.字符串(str) 内容详细 1.整型 Python中的整型用int表示. 1.python2中: 在32位机器上,整数的位数 ...
- .Net C# 泛型序列化和反序列化JavaScriptSerializer
项目添加引用System.Web.Extensions /// <summary> /// 泛型序列化 /// </summary> public class JsonHelp ...
- LCA(最近公共祖先)
学习链接:https://baike.baidu.com/item/%E4%BC%B8%E5%B1%95%E6%A0%91/7003945?fr=aladdin 求LCA的方法有很多,在这里就只介绍一 ...
- Unity QualitySettings.vSyncCount 垂直同步数
QualitySettings.vSyncCount 垂直同步数 Description 描述 The VSync Count. 垂直同步数. The number of VSyncs that sh ...