`
357029540
  • 浏览: 725479 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论

如何保证在Java多线程中的原子性操作?

    博客分类:
  • JAVA
阅读更多

       在单线程的模式下,我们针对某个变量的修改是不会产生数据的脏读和脏写的,因为它只有一个操作来对变量进行读写操作,但是在多线程模式下就不一样了,如果多个线程对一个变量进行修改操作,那么到底哪一个线程修改的值才是最后的值呢?同时是不是我们需要的值呢?那么我们如何来保证多个线程修改变量值的时候保证变量的原子操作?简单说明下原子操作就是一个步骤要么操作全部成功,要么失败。我们看下i++这个操作,对于不了解这个i++操作生成的二进制文件的具体同学来说,可能会认为它是只有一个操作步骤的运算操作,但是实际情况肯定不是的,它首先会去获取字段i,然后在获取i的值,然后在进行加1操作,最后对i进行赋值,这里就进行了4个步骤,如果在第2个步骤的时候另外一个线程也来进行了i++操作,那么可想而知最终得到的结果可能就不是自己想要的了。那么我们如何保证i++的原子操作呢?这个时候肯定大家也能想到用同步啊,synchronized关键字和Lock锁都可以进行同步的控制,当然这也是正确的,但是我们今天所说的多线程原子操作是通过jdk提供的JUC包实现的原子操作,如AtomicInteger,AtomicReference等原子操作类,在JUC包中的原子类操作基本都实现了CAS(compare and swap)操作,当对某个值进行改变时CAS会先对当前值进行比较,如果正确才进行值的交换即更新值,CAS操作是在硬件资源上直接进行的操作,是由处理器提供的内存操作指令,由其保证原子性。通过查看相关的JUC包,可以看到很多Unsafe类方法的使用,这个类提供了很多native方法的使用,因为是不安全的类,所以自己想使用的话,必须自己去通过反射进行获取来进行操作。

        虽然说JUC包提供了很多原子的CAS操作,但是它一次只能针对一个变量进行CAS操作,不能进行多个变量的操作,同时因为要不停的进行CAS的判断和交换值操作,所以线程会一直处于高频的运行中,如果其中一个线程处理时间过长,那么就会带来CPU的高性能消耗,同时CAS操作还会出现一种叫做ABA的问题,即当前值是A,将它换做B,然后又由B换做A,那么就无法判断A是否在这期间发生过变化,因为最终值没有变化,如果在AB的时候有其他线程来进行了操作A操作,而该线程在休眠时间内又从B变回了A,而此时A的指向已经发生改变,那这种改变带来的结果是其他线程对A的操作已经发生改变,得到的结果也可能发生变化,那么怎么来解决这个ABA的问题呢?我们可以采用类似版本号的控制机制来实现避免ABA这种问题,在JUC包中提供了AtomicStampedReference类,它提供了一个版本控制的判断,我们使用以下代码运行后可以看到不同的结果

public class AtomicStampedReferenceTest {
 
    public static void main(String [] args){
        AtomicStampedReference reference = new AtomicStampedReference(0,0);
        new Thread(() ->{
            reference.compareAndSet(0,1,0,1);
            System.out.println(reference.getReference() + "--->" + reference.getStamp());
        }).start();
 
        new Thread(() ->{
            reference.compareAndSet(0,1,1,2);
            System.out.println(reference.getReference() + "--->" + reference.getStamp());
        }).start();
 
        new Thread(() ->{
            reference.compareAndSet(1,2,1,2);
            System.out.println(reference.getReference() + "--->" + reference.getStamp());
        }).start();
    }

 

0
0
分享到:
评论

相关推荐

    java多线程中的原子操作

    NULL 博文链接:https://peter8015.iteye.com/blog/975250

    java多线程安全性基础介绍.pptx

    java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...

    Java多线程中提到的原子性和可见性、有序性1

    如果应场景需要个更范围的原性保证,Java内存模型还提供了lock和unlock操作来满这种需求,尽管虚拟机未把lock与unlock操作直接开放给户使,但是却

    Java多线程:AtomicIntegerArray 原子更新数组类.docx

    原子更新数组类顾名思义,通过原子的方式更新数组里的某个元素,Atomic包提供了以下三个类: AtomicIntegerArray:原子更新整型数组里的元素。 AtomicLongArray:原子更新长整型数组里的元素。 ...

    java并发理论基础、可见性、原子性、有序性详解

    本资源涵盖了Java并发编程的理论基础和实践,主要包括可见性、原子性和有序性的详细介绍,以及多线程的使用原因、好处和坏处等方面...我们还将讲解Java多线程开发的好处和坏处,并探讨如何尽量减少由多线程带来的问题。

    2万字Java并发编程面试题合集(含答案,建议收藏)

    3、什么是多线程中的上下文切换?4、死锁与活锁的区别,死锁与饥饿的区别?5、Java 中用到的线程调度算法是什么?6、什么是线程组,为什么在 Java 中不推荐使用?7、为什么使用 Executor 框架?8、在 Java 中 ...

    Java 多线程与并发(8-26)-JUC原子类- CAS, Unsafe和原子类详解.pdf

    Java 多线程与并发(8_26)-JUC原子类_ CAS, Unsafe和原子类详解

    Java多线程安全问题和锁

    文章目录多线程安全问题和锁线程在jvm中的特点锁的出现synchronized 关键字-监视器锁monitor lock死锁的产生和避免 什么是线程安全问题? 当多个线程同时操作同一个数据是,可能会出现数据不一样的情况,这就是线程...

    详解java多线程的同步控制

    同步控制是并发程序必不可少的重要手段,本文我们将通过重入锁、读写锁、信号量、倒计数器和循环...保证了共享内存的原子性、可见性、有序性 JMM原理图 线程在访问主内存中的变量时并不是直接对主存中的变量进行读写,

    92道Java多线程与并发面试题含答案(很全)

    Java并发编程的核心概念包括: 线程(Thread):线程是程序执行流的最小单元。...原子操作(Atomic Operations):原子操作是不可中断的操作,即在多线程环境中,这些操作要么完全执行,要么完全不执行。

    Java多线程Atomic包操作原子变量与原子类详解

    主要介绍了Java多线程Atomic包操作原子变量与原子类详解,简单介绍了Atomic,同时涉及java.util.concurrent中的原子变量,Atomic类的作用等相关内容,具有一定参考价值,需要的朋友可以了解下。

    举例解析Java多线程编程中需要注意的一些关键点

    主要介绍了Java多线程编程中需要注意的一些关键点,包括ThreadLocal变量与原子更新等一些深层次的内容,需要的朋友可以参考下

    使用Java的Memory Model实现一个简单的计数器.txt

    这个代码实现了一个简单的计数器,使用了Java的`AtomicInteger`类来保证多线程环境下的原子性操作。`AtomicInteger`是一个支持原子操作的整数类,它内部使用了CAS(Compare And Swap)算法来实现线程安全的操作。在...

    concurrent 多线程 教材

    02 Java 程序中的多线程 03 编写多线程的 Java 应用程序 04 如果我是国王:关于解决 Java编程语言线程问题的建议 (2) 05 构建Java并发模型框架 (2) 06 Java 技术: 使您轻松地进行多线程应用程序编程 07 使用...

    Sparklingredstar#JavaBooks#Java多线程-Atomic原子类1

    引言JavaGuide :一份涵盖大部分Java程序员所需要掌握的核心知识。star:45159,替他宣传一下子这位大佬,总结的真好!我引用这位大佬的文章,因为

    Java多线程和并发知识整理

    1.1为什么需要多线程 1.2不安全示例 1.3并发问题的根源 1.4JMM 1.5线程安全的分类 1.6线程安全的方法 二、线程基础 2.1状态 2.2使用方式 2.3基础机制 2.4中断 2.5互斥同步 2.6线程合作 三、...

    java面试题-java-interview-questions-master.zip

    java面试题_java-interview-questions-master.zip2、在 Java 程序中怎么保证多线程的运行安全? 出现线程安全问题的原因一般都是三个原因: 1、 线程切换带来的原子性问题 解决办法:使用多线程之间同步...

    Java并发编程相关源码集 包括多任务线程,线程池等.rar

     volatile关键字的非原子性、volatile关键字的使用、AtomicInteger原子性操作、线程安全小例子:多个线程竞争问题、多个线程多个锁问题、创建一个缓存的线程池、多线程使用Vector或者HashTable的示例(简单线程同步...

    针对于Executor框架,Java API,线程共享数据

    Executor框架是Java并发编程中的一个重要工具,它提供了一种管理...原子操作在并发编程中具有重要的作用,可以保证多个线程对同一个变量的操作是线程安全的。 在两个线程之间共享数据,可以通过以下几种方式实现:

    【2018最新最详细】并发多线程教程

    【2018最新最详细】并发多线程教程,课程结构如下 1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗...

Global site tag (gtag.js) - Google Analytics