精华内容
下载资源
问答
  • JAVA原子性操作
    2021-02-26 09:17:35

    java 原子性操作

    Java中的原子操作包括: 1)除long和double之外的基本类型的赋值操作

    2)所有引用reference的赋值操作

    3)java.concurrent.Atomic.* 包中所有类的一切操作

    count++不是原子操作,是3个原子操作组合

    1.读取主存中的count值,赋值给一个局部成员变量tmp 2.tmp+1 3.将tmp赋值给count

    要使用AtomicInteger.getAndIncrement()才可以避免并发问题

    原子性操作与加锁实例:

    package com.yy.ent.antiad.common.util;

    import java.util.concurrent.atomic.AtomicInteger;

    /**

    * 原子性自增与加锁方式对比

    * @author huangyucai1@yy.com

    * @since 2016-6-2

    */

    public class AtomicTest {

    private int value;

    public AtomicTest(int value){

    this.value = value;

    }

    public synchronized int increase(){

    return value++;

    }

    public int getValue(){

    return value;

    }

    public static void main(String args[]){

    long start = System.currentTimeMillis();

    AtomicTest test = new AtomicTest(0);

    for( int i=0;i< 100000000;i++){

    test.increase();

    }

    long end = System.currentTimeMillis();

    System.out.println(test.getValue()+" times increase synchronize time cost:"+(end -start)+" ms");

    start = System.currentTimeMillis();

    AtomicInteger atomic = new AtomicInteger(0);

    for(int i=0;i< 100000000;i++){

    atomic.incrementAndGet();

    }

    end = System.currentTimeMillis();

    System.out.println(atomic.intValue() +" times increase atomic time cost:"+(end - start)+" ms" );

    }

    }

    运行结果

    100000000 times increase synchronize time cost:2857 ms

    100000000 times increase atomic time cost:1033 ms

    更多相关内容
  • java原子性操作,volatile

    2018-03-02 02:42:09
    可是虚拟机规范中规定的assign,store,write才是原子性操作,万一这三步执行中间时刻,有其他线程读取了数据,那怎么办? 还有一点,对于多线程来说:比如线程A和B,同时执行了对全局变量c的write原子操作,那怎么处理?谁会先...
  • JMM学习之Java实现原子性操作

    千次阅读 2021-06-12 17:18:50
    1 、具有原子性安全问题的代码 public class AtomicityJMM { private int i=0; private void increase() { try { //可以增加延迟,效果更明显 Thread.sleep(100); i++; } catch (InterruptedException e) { ...

    以计数器为例:

    1 、具有原子性安全问题的代码

    public class Counter {
     	private int i=0;
        private  void increase() {
            try {
                //可以增加延迟,效果更明显
                Thread.sleep(100);
                i++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            List<Thread> list = new ArrayList<>(10000);
            Counter counter = new Counter();
            for (int j = 0; j < 1000; j++) {
                Thread thread = new Thread(() -> {
                    for (int m = 0; m < 5; m++) {
                        counter.increase();
                    }
                },j+"");
                list.add(thread);
            }
            for (Thread thread : list) {
                thread.start();
            }
            try {
                for (Thread thread : list) {
                    thread.join();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(counter.i);
        }
    }
    

    多次执行结果

    4887 4896
    

    多次执行结果不一样,并且理想结果应该5000

    2、使用循环CAS使用原子操作

    public class Counter {
        private  AtomicInteger atomicInteger = new AtomicInteger(0);
        // 使用cas自旋,满足条件时再自增
        private   void increase() {
            for (;;) {
                int i = atomicInteger.get();
                //使用unsafe类的compareAndSwapInt方法,检查旧值有没有发生,如果发生变化则不交换,如果没有发生变化则交换。这个过程是原子性的,所有可以保证原子性
                boolean res = atomicInteger.compareAndSet(i, ++i);
                if (res) {
                    break;
                }
            }
        }
        public static void main(String[] args) {
            List<Thread> list = new ArrayList<>(10000);
            Counter counter = new Counter();
            for (int j = 0; j < 1000; j++) {
                Thread thread = new Thread(() -> {
                    for (int m = 0; m < 5; m++) {
                        counter.increase();
                    }
                },j+"");
                list.add(thread);
            }
            for (Thread thread : list) {
                thread.start();
            }
            try {
                for (Thread thread : list) {
                    thread.join();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(counter.atomicInteger.get());
        }
    }
    

    3、使用JDK提供的工具类

    public class Counter {
        private  AtomicInteger atomicInteger = new AtomicInteger(0);
        public static void main(String[] args) {
            List<Thread> list = new ArrayList<>(10000);
            Counter counter = new Counter();
            for (int j = 0; j < 1000; j++) {
                Thread thread = new Thread(() -> {
                    for (int m = 0; m < 5; m++) {
                        counter.atomicInteger.incrementAndGet();
                    }
                },j+"");
                list.add(thread);
            }
            for (Thread thread : list) {
                thread.start();
            }
            try {
                for (Thread thread : list) {
                    thread.join();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(counter.atomicInteger.get());
        }
    }
    

    4、使用锁机制实现原子操作

    public class Counter {
    
        private int i=0;
        private  void increase() {
            try {
                Thread.sleep(100);
                //要尽量减少锁范围
                synchronized(this) {
                    i++;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            List<Thread> list = new ArrayList<>(10000);
            Counter counter = new Counter();
            for (int j = 0; j < 1000; j++) {
                Thread thread = new Thread(() -> {
                    for (int m = 0; m < 5; m++) {
                        counter.increase();
                    }
                },j+"");
                list.add(thread);
            }
            for (Thread thread : list) {
                thread.start();
            }
            try {
                for (Thread thread : list) {
                    thread.join();
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(counter.i);
        }
    }
    
    展开全文
  • 关于Java原子性操作的理解(赋值和自增自减) 文章目录关于Java原子性操作的理解(赋值和自增自减)赋值操作是否是原子性?自增自减操作是否是原子性的? 赋值操作是否是原子性? 不是,不管是基础数据类型还是引用数据...

    关于Java原子性操作的理解(赋值和自增自减)

    赋值操作是否是原子性?

    不是,不管是基础数据类型还是引用数据类型,它都不是原子操作
    【当然,如果以结果论的话,局部变量基本数据类型的赋值操作(long、double可能受到jvm、os等影响造成非原子性赋值),局部引用类型的null值赋值都是原子性的!】
    int赋值int类型的赋值

    booleanl类型的赋值
    booleanl类型的赋值,果然JVM是将boolean当成int来处理呢,ture是1,false是0

    double类型的赋值
    double类型的赋值

    引用类型的赋值
    引用类型的赋值

    由此可见,在Java中任何赋值操作都不是原子操作!它都具有先将被赋入的值加入到栈中,然后在赋值给变量。至于int a = b,这种方式的赋值则也不是原子操作,因为他需要先load b变量的值到栈中,然后在赋值给a,如下图所示:
    int a = b
    int a = b操作

    自增自减操作是否是原子性的?

    只有局部变量的int类型,且自增自减的幅度在-32768 ~ 32767时,局部变量的int类型的自增自减操作都是通过iinc或iinc_w一条指令完成的,而其他数据类型则一定需要有压栈、运算、存回的操作。

    自增自减
    局部变量int自增自减,幅度在-32768 ~ 32767

    局部变量int自增自减,幅度超过-32768 ~ 32767
    局部变量int自增自减,幅度超过-32768 ~ 32767

    对象成员变量的自增自减操作
    对象成员变量的自增自减操作

    类变量的自增自减操作
    类变量的自增自减操作

    byte的自增自减操作
    byte的自增自减操作

    其他就不一一举例了,都是大同小异。

    展开全文
  • Atomic: Atomic包是java.util.concurrent下的另一个专门为线程安全设计的java的包,包含多个原子性操作的类。基本特性就是在多线程情况下,当多个线程想要同时操作这些类的某些实例方法时,具有排他性,也就是当...

    Atomic:

        Atomic包是java.util.concurrent下的另一个专门为线程安全设计的java的包,包含多个原子性操作的类。基本特性就是在多线程情况下,当多个线程想要同时操作这些类的某些实例方法时,具有排他性,也就是当某个线程在执行某个方法时,不会被其他线程打断,其他线程会在外部等待,一直等到该方法执行完毕,才由JVM从等待队列中选择另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(只是在硬件级别去阻塞了)。可以对基本数据,数组中的基本数据,对类中的基本数据进行操作。原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读写操作。

        我们先看一下传统的锁是怎样保证线程安全的

        

    class LockDemo {
    
        private int a;
    
        public synchronized void setA(int b) {
            this.a = b;
        }
    
        public synchronized int getA() {
            return a;
        }
    
        public synchronized void addA() {
            ++a;
        }
    
        public synchronized void reduceA() {
            --a;
        }
    
    }

    其实这样的synchronized已经能满足我们日常的线程安全需求了,synchronized是基于代码阻塞的机制,也就是当某个线程占用资源时,其他线程是无法进入的,如果这个线程出现问题的时候,出现大量线程阻塞,CPU就会耗费大量资源来处理阻塞在外的这些线程,但是CPU的任务本不该如此,还极可能出现死锁等问题,对于这样的简单操作反而显得有些笨重,所以应该有更合适更高效的方法来处理这样的问题。所以就有了CAS

    Compare and swap(CAS)

    当前的处理器基本都支持CAS,这是一种基于硬件的处理,每一个CAS操作都包含三个运算符:内存地址V , 一个期望值A和新值B,操作的时候如果这个地址上存放的值等于期望的值A,那么就赋值为B,如果没有,那么就不做任何操作。简而言之,你的值和我的期望值相等,就给你新值,否则不干活了。

    我们自己可以简单的模拟一下CAS的实现

    class CASDemo {
    
        private int value;
    
        public synchronized int getValue() {
            return value;
        }
    
        public synchronized int cas(int expectValue , int newValue) {
    
            int oldValue = value;
            if(value == expectValue) {
                value = newValue;
            }
            return oldValue;
    
        }
    
    }
    
    class CASTest {
    
        private CASDemo casDemo;
    
        public int getValue () {
            return casDemo.getValue();
        }
    
        public int add () {
            int oldValue = casDemo.getValue();
            while(casDemo.cas(oldValue , oldValue + 1) != oldValue) {
                oldValue = casDemo.getValue();
            }
    
            return oldValue + 1;
        }
    
    }

    看下Atomic包


    看一下AtomicInteger类是怎么处理自增的处理的,也就是方法getAndIncrement()


    这里调用了一个叫做Unsafe类的方法,这个类比较特殊内部大多是native的方法,而且这个类也不允许我们随意使用,当然JDK自己是可以用的,(ps:处于凡是试试的态度,我试了一下调用它的方法,报错如下)

    看一下valueOffset是哪来的

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    这里又调用了Unsafe类的一个方法,参数是通过反射获取的AtomicInteger的value属性,也就是它的值

    继续进

    public native long objectFieldOffset(Field var1);


    很可惜,是一个本地方法,查看文档可知,这个方法返回的就是"原来的值"的内存地址 , valueOffset的值(ps:文档是其他某位大神那里借来的)

    返回一开始的方法 点进去看

    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;
    }

    参数比较混乱 var2就是valueOffset 继续跟进

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    喔,又是一个本地方法,参数很乱  按我们之前的讲就是:

     var2(valueOffset)  , var4(expectValue) , var5(newValue) 

    我再借一点注释


    这个方法原子的将变量的值更新为var5,如果成功了返回true。这样返回去取反即为false,循环结束,返回var5,取到新值。

    当然Unsafe关于CAS的方法都是本地方法,是由C语言实现的,我们这里是看不到具体实现细节的。


        说了半天 到底CAS是怎么保证线程安全的呢,其实在语言层次我们是没有做任何关于同步的操作的,也没有任何锁。Atomic包下这些类将这些操作都交给了CPU和内存,利用CPU多处理的能力,实现硬件的阻塞,再加上volatile变量的特性即可实现基于原子性的操作的线程安全。所以CAS不是没有阻塞 ,只是阻塞不是语言层面,而是在硬件层面,这样便会更高效。



        

    展开全文
  • Java中的原子性和原子操作

    千次阅读 2019-06-28 12:41:31
    原子性:即一个操作或者多个操作 要么全部执行 并且执行的过程不会被任何因素打断,要么就都不执行。 举个例子:假如为一个32位的变量赋值过程不具备原子性的话,会发生什么后果? int i=9; 假若一个线程执行...
  • java并发编程之原子性操作

    千次阅读 2018-07-05 16:43:26
    java中自带了一些原子性操作,比如给一个非long、double基本数据类型变量或者引用的赋值或者读取操作。 为什么强调非 long 、 double 类型的变量?我们稍后看哈~ 那 i++ 这个操作不是一个 原子性操作 么? 答:还真...
  • Java中的原子操作

    万次阅读 2019-05-11 10:42:36
    文章目录1、什么是原子操作2、Java中原子操作的实现方式2.1 用CAS实现原子操作2.1.2 使用CAS实现原子操作2.1.3 CAS实现原子操作的问题3、Java中使用锁实现原子操作4、CPU如何实现原子操作 1、什么是原子操作 原子...
  • Java实现i++原子性操作

    千次阅读 2020-03-14 15:32:43
    Java实现i++原子性操作1、cas 实现i++原子性 i++在并发过程中是属于线程不安全的,因为i++不具有原子性。只要解决了i++的原子性问题,那么它就是属于线程安全的了。(废话一大堆……) 1、cas 实现i++原子性 ...
  • 主要介绍了java 并发中的原子性与可视性实例详解的相关资料,原子性是说一个操作是否可分割。可见性是说操作结果其他线程是否可见。需要的朋友可以参考下
  • 分布式Redis原子操作示例,近期项目中遇到分布式项目中多节点大并发操作redis同一个key。此案例利用java调用LUA脚本实现redis操作原子性。分享出来大家参考。
  • 什么是java原子性原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么必然包括2个...
  • 主要介绍了Java多线程Atomic包操作原子变量与原子类详解,简单介绍了Atomic,同时涉及java.util.concurrent中的原子变量,Atomic类的作用等相关内容,具有一定参考价值,需要的朋友可以了解下。
  • JAVA操作REDIS执行原子操作

    千次阅读 2022-04-26 14:07:03
    JAVA操作REDIS执行原子操作JAVA操作REDIS执行原子操作为什么要使用原子操作 JAVA操作REDIS执行原子操作 为什么要使用原子操作 众所周知,redis 作为数据库的前置库,给数据库使用节省了很多请求,很多请求再查询缓存...
  • 17.7.Non-Atomic Treatment of double and longFor the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: on....
  • 除了long和double之外的基本类型的赋值操作,因为long和double类型是64位的,所以它们的操作在32位机器上不算原子操作,而在64位的机器上是原子操作。...java.concurrent.Atomic *包中所有类的原子操作 ...
  • java如何实现原子操作

    2021-06-20 18:31:14
    java中可以通过锁和循环CAS 的方式来实现原子操作。 i.使用循环CAS的方式来实现原子操作 在JDK的并发包里面提供一些类来支持原子操作,如AtomicBoolean(用原子方式来更新boolean值),AtomicInterger(原子方式...
  • 原子性原子性是指一个线程的操作是不能被其他线程打断,同一时间只有一个线程对一个变量进行操作。在多线程情况下,每个线程的执行结果不受其他线程的干扰,比如说多个线程同时对同一个共享成员变量n++100次,如果...
  • JAVA的原子性和可见性的理解 这篇博客主要解决两个问题: 1. 原子性和可见性的区别 ...例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。 (2)可见性volatile修饰词,可以应对多线程同时访问修改同一...
  • Java中,对基本数据类型的变量的读取和赋值操作是原子性操作,即这些操作是不可被中断的,要么执行,要么不执行。 上面一句话虽然看起来简单,但是理解起来并不是那么容易。看下面一个例子: x = 10; //语句1 y =...
  • Java如何实现原子操作

    2020-02-06 20:31:10
    Java中可以通过锁和循环CAS的方式来实现原子操作。 (1)使用循环CAS实现原子操作 ​ JVM中的CAS操作正是利用了处理器提供的CMPXCHG指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。 (2)...
  • Java原子性&&可见性&&有序性

    万次阅读 2017-06-21 10:16:53
    Java原子性&&可见性&&有序性原子性定义:原子性:是指一个操作或多个操作要么全部执行,且执行的过程不会被任何因素打断,要么就都不执行。原子操作原理(处理器是如何实现原子操作的)处理器实现原子操作有3种...
  • java 数据操作 原子性

    千次阅读 2019-03-27 18:37:37
    java中 基本类型简单的赋值操作都属于原子操作 比如 int x;x=10; 又比如y=x; x++;等操作其实是两步操作,单步都是原子操作,合起来就不是了,再多线程高并发下就会出现问题 valatile关键字保证了可见,被修改的值会...
  • Java多线程之原子性操作

    千次阅读 2018-03-09 21:59:48
    何谓原子性操作,即为最小的操作单元,比如i=1,就是一个原子性操作,这个过程只涉及一个赋值操作。又如i++就不是一个原子操作,它相当于语句i=i+1;这里包括读取i,i+1,结果写入内存三个操作单元。因此如果操作不...
  • Java代码保证操作原子性

    千次阅读 2019-05-14 11:57:32
    创建java.util.concurrent.atomic.AtomicBoolean类的实例对象, 运用:在接口项目中的dao层查询时 public static AtomicBoolean notify = new AtomicBoolean(false); 线程中 new Thread() { public void run...
  • Java 原子性和可见性理解

    千次阅读 2018-07-06 17:28:39
    1、原子性 (1)原子是构成物质的基本单位(当然电子等暂且不论),所以原子的意思代表着——“不可分...例如 a=1是原子性操作,但是a++和a +=1就不是原子性操作。 &amp;nbsp;2、非原子性 也就是整个过程中会出...
  • Java多线程之原子性

    千次阅读 2018-05-18 14:39:23
    友情提示:作为一个java小白最近在看java多线程知识,...我准备先回顾一下非常基础而且重要的知识点,先从三个特性下手,原子性,可见性,有序性。每一点的内容都很多,一点一点来,先介绍原子性原子性: 定...
  • Java线程安全中的原子性操作

    千次阅读 2020-04-02 23:13:46
    原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序不可以被打乱,...一个是JDK中已经提供好的Atomic包,他们均使用了CAS完成线程的原子性操作。 另一个是使用锁的机制来处理线程之间的原子性。锁包括synch...
  • 在第一篇文章01并发编程的Bug源头当中,讲到了把一个或者多个操作在 CPU 执行的过程中不被中断的特性称为原子性,那么原子性的问题该如何解决。 同一时刻只有一个线程执行这个条件非常重要,我们称为互斥,如果能...
  • Java 8大原子操作

    千次阅读 2020-05-06 21:54:03

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 189,393
精华内容 75,757
关键字:

java原子性操作

java 订阅
友情链接: Syn_FIFO.zip