java 中原子操作什么意思(请问java中的原子操作有哪些)
大家好,今天来为大家分享java 中原子操作什么意思的一些知识点,和请问java中的原子操作有哪些的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!
Java多线程之Atomic:原子变量与原子类
一何谓Atomic?
Atomic一词跟原子有点关系后者曾被人认为是最小物质的单位计算机中的Atomic是指不能分割成若干部分的意思如果一段代码被认为是Atomic则表示这段代码在执行过程中是不能被中断的通常来说原子指令由硬件提供供软件来实现原子方法(某个线程进入该方法后就不会被中断直到其执行完成)
在x平台上 CPU提供了在指令执行期间对总线加锁的手段 CPU芯片上有一条引线#HLOCK pin如果汇编语言的程序中在一条指令前面加上前缀 LOCK经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低持续到这条指令结束时放开从而把总线锁住这样同一总线上别的CPU就暂时不能通过总线访问内存了保证了这条指令在多处理器环境中的原子性
二 ncurrent中的原子变量
无论是直接的还是间接的几乎 ncurrent包中的所有类都使用原子变量而不使用同步类似 ConcurrentLinkedQueue的类也使用原子变量直接实现无等待算法而类似 ConcurrentHashMap的类使用 ReentrantLock在需要时进行锁定然后 ReentrantLock使用原子变量来维护等待锁定的线程队列
如果没有 JDK中的 JVM改进将无法构造这些类这些改进暴露了(向类库而不是用户类)接口来访问硬件级的同步原语然后 ncurrent中的原子变量类和其他类向用户类公开这些功能
ncurrent atomic的原子类
这个包里面提供了一组原子类其基本的特性就是在多线程环境下当有多个线程同时执行这些类的实例包含的方法时具有排他性即当某个线程进入方法执行其中的指令时不会被其他线程打断而别的线程就像自旋锁一样一直等到该方法执行完成才由JVM从等待队列中选择一个另一个线程进入这只是一种逻辑上的理解实际上是借助硬件的相关指令来实现的不会阻塞线程(或者说只是在硬件级别上阻塞了)其中的类可以分成组
AtomicBoolean AtomicInteger AtomicLong AtomicReference
AtomicIntegerArray AtomicLongArray
AtomicLongFieldUpdater AtomicIntegerFieldUpdater AtomicReferenceFieldUpdater
AtomicMarkableReference AtomicStampedReference AtomicReferenceArray
其中AtomicBoolean AtomicInteger AtomicLong AtomicReference是类似的
首先AtomicBoolean AtomicInteger AtomicLong AtomicReference内部api是类似的举个AtomicReference的例子
使用AtomicReference创建线程安全的堆栈
Java代码
public class LinkedStack<T>{
private AtomicReference<Node<T》 stacks= new AtomicReference<Node<T》()
public T push(T e){
Node<T> oldNode newNode;
while(true){//这里的处理非常的特别也是必须如此的
oldNode= stacks get()
newNode= new Node<T>(e oldNode)
if(pareAndSet(oldNode newNode)){
return e;
}
}
}
public T pop(){
Node<T> oldNode newNode;
while(true){
oldNode= stacks get()
newNode= oldNode next;
if(pareAndSet(oldNode newNode)){
return oldNode object;
}
}
}
private static final class Node<T>{
private T object;
private Node<T> next;
private Node(T object Node<T> next){
this object= object;
this next= next;
}
}
}
然后关注字段的原子更新
AtomicIntegerFieldUpdater<T>/AtomicLongFieldUpdater<T>/AtomicReferenceFieldUpdater<T V>是基于反射的原子更新字段的值
相应的API也是非常简
单的但是也是有一些约束的
()字段必须是volatile类型的!volatile到底是个什么东西请查看
()字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致也就是说调用者能够直接操作对象字段那么就可以反射进行原子操作但是对于父类的字段子类是不能直接操作的尽管子类可以访问父类的字段
()只能是实例变量不能是类变量也就是说不能加static关键字
()只能是可修改变量不能使final变量因为final的语义就是不可修改实际上final的语义和volatile是有冲突的这两个关键字不能同时存在
()对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段不能修改其包装类型(Integer/Long)如果要修改包装类型就需要使用AtomicReferenceFieldUpdater
在下面的例子中描述了操作的方法
[java]
import ncurrent atomic AtomicIntegerFieldUpdater;
public class AtomicIntegerFieldUpdaterDemo{
class DemoData{
public volatile int value=;
volatile int value=;
protected volatile int value=;
private volatile int value=;
}
AtomicIntegerFieldUpdater<DemoData> getUpdater(String fieldName){
return AtomicIntegerFieldUpdater newUpdater(DemoData class fieldName)
}
void doit(){
DemoData data= new DemoData()
System out println(==>+getUpdater( value) getAndSet(data))
System out println(==>+getUpdater( value) incrementAndGet(data))
System out println(==>+getUpdater( value) decrementAndGet(data))
System out println( true==>+getUpdater( value) pareAndSet(data))
}
public static void main(String[] args){
AtomicIntegerFieldUpdaterDemo demo= new AtomicIntegerFieldUpdaterDemo()
demo doit()
}
}
在上面的例子中DemoData的字段value/value对于AtomicIntegerFieldUpdaterDemo类是不可见的因此通过反射是不能直接修改其值的
AtomicMarkableReference类描述的一个<Object Boolean>的对可以原子的修改Object或者Boolean的值这种数据结构在一些缓存或者状态描述中比较有用这种结构在单个或者同时修改Object/Boolean的时候能够有效的提高吞吐量
AtomicStampedReference类维护带有整数标志的对象引用可以用原子方式对其进行更新对比AtomicMarkableReference类的<Object Boolean> AtomicStampedReference维护的是一种类似<Object int>的数据结构其实就是对对象(引用)的一个并发计数但是与AtomicInteger不同的是此数据结构可以携带一个对象引用(Object)并且能够对此对象和计数同时进行原子操作
在本文结尾会提到 ABA问题而AtomicMarkableReference/AtomicStampedReference在解决 ABA问题上很有用
三 Atomic类的作用
使得让对单一数据的操作实现了原子化
使用Atomic类构建复杂的无需阻塞的代码
访问对个或个以上的atomic变量(或者对单个atomic变量进行次或次以上的操作)通常认为是需要同步的以达到让这些操作能被作为一个原子单元
无锁定且无等待算法
基于 CAS(pare and swap)的并发算法称为无锁定算法因为线程不必再等待锁定(有时称为互斥或关键部分这取决于线程平台的术语)无论 CAS操作成功还是失败在任何一种情况中它都在可预知的时间内完成如果 CAS失败调用者可以重试 CAS操作或采取其他适合的操作
如果每个线程在其他线程任意延迟(或甚至失败)时都将持续进行操作就可以说该算法是无等待的与此形成对比的是无锁定算法要求仅某个线程总是执行操作(无等待的另一种定义是保证每个线程在其有限的步骤中正确计算自己的操作而不管其他线程的操作计时交叉或速度这一限制可以是系统中线程数的函数例如如果有个线程每个线程都执行一次CasCounter increment()操作最坏的情况下每个线程将必须重试最多九次才能完成增加)
再过去的年里人们已经对无等待且无锁定算法(也称为无阻塞算法)进行了大量研究许多人通用数据结构已经发现了无阻塞算法无阻塞算法被广泛用于操作系统和 JVM级别进行诸如线程和进程调度等任务虽然它们的实现比较复杂但相对于基于锁定的备选算法它们有许多优点可以避免优先级倒置和死锁等危险竞争比较便宜协调发生在更细的粒度级别允许更高程度的并行机制等等
常见的
非阻塞的计数器Counter
非阻塞堆栈ConcurrentStack
lishixinzhi/Article/program/Java/gj/201311/27474Java 中对引用类型的变量赋值是原子操作吗
由一个简单的例子引出并发处理时容易被忽视的陷阱,用来作为面试问题应该很适合。
某日,工作了 4年多的 Java程序员小 K跳槽,面试时碰到这样一个题目....
public class P1{
private long b= 0;
public void set1(){
b= 0;
}
public void set2(){
b=-1;
}
public void check(){
System.out.println(b);
if(0!= b&&-1!= b){
System.err.println("Error");
}
}
}
问题
调用 set1()、set2()、check(),会打印出 Error么?
小K的推理
“无论如何调用 set1()、set2()-> b的值只可能是 0或-1->在 check()里面的判断条件(b既不为 0也不为-1)永远不成立->不打印 Error”
小 K觉得有坑:这题目应该不会这么简单,再考虑一下多线程环境。
请问java中的原子操作有哪些
13是, 24不是,但并不是楼上说的意思哦,原子操作可以和多线程结合起来看。
首先楼主你要知道原子操作是什么,我的理解是符合多线程原子性操作的操作就叫原子操作。
原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型)这个操作
是不可分割的,那么我们说这个操作是原子操作。再比如:a++;这个操作实际是a= a+ 1;
是可分割的,所以他不是一个原子操作。
例如:你执行a= 1这个操作的时候,是没有任何问题的,但是当你执行a= b的时候就有很大的问题了
假如这个时候别的线程改变了b的值,那么a= b就会出现不同的结果,因为b的值你并不能确定,
比如你第期望的是a= b,你认为b的值是3,所以a也是3,可是多线程情况下程序使b变成了
4,那么a也就变成了4,那这就不算一个原子操作。
好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!