美文网首页
Java中的原子性和可见性

Java中的原子性和可见性

作者: e小e | 来源:发表于2017-11-08 08:28 被阅读302次

原子性:在java语言原子性是指的一个不可以分割的操作,比如说 a = 0,这个就具有原子性,如果是a++, 这个操作其实是 a = a+1; 是可以分割的,所以他就不是一个原子性操作。
非原子操作具有线程安全问题,我们需要使用相关的手段,保证线程同步,java.util.concurrent.atomic包下面提供了一系列的原子操作类,如AtomicInteger、AtomicLong、AtomicReference等

可见性:是指线程之间的可见性,当一个线程修改一个变量,另外一个线程可以马上得到这个修改值。比如:用volatile修饰的变量是具有可见性的。volatile修饰的变量不允许线程内部缓存和
重新排序,即直接修改内存,所以对其它线程是可见的。但是这里需要注意一个问题volatile修饰的变量只是具有可见性,而不具备原子性。比如 volatile int a = 0; 之后操作一个 a++,那么a只是具有可见性,而
不具备原子性,a++同样具有线程安全的问题。

他们之间关系
原子性是一个操作是否一步完成,可见性是指其它线程是否可见。它们其实并没有任何关系。

public class Test {  
  
    volatile int a = 1;  
    volatile boolean ready;  
      
    public class PrintA extends Thread{  
        @Override  
        public void run() {  
            while(!ready){  
                Thread.yield();  
            }  
            System.out.println(a);  
        }  
    }  
    public static void main(String[] args) throws InterruptedException {  
        Test t = new Test();  
        t.new PrintA().start();  
        //下面两行如果不加volatile的话,执行的先后顺序是不可预测的。并且下面两行都是原子操作,但是这两行作为一个整体的话就不是一个原子操作。  
        t.a = 48; //这是一个原子操作,但是其结果不一定具有可见性。加上volatile后就具备了可见性。  
        t.ready = true;//同理  
    }  
  
}  

上面程序如果变量a不用volatile修饰那么输出结果很可能就是0.。

AtomicInteger、AtomicLong、AtomicBoolean,AtomicReference前三个都很好理解是对Integer,Long,Boolean做原子性操作的类,那这个AtomicReference是什么呢?
它主要是对引用对象进行原子性操作:举个栗子。

class Person {  
    volatile long id;  
    public Person(long id) {  
        this.id = id;  
    }  
    public String toString() {  
        return "id:"+id;  
    }
public static void main(String[] args){  
  
        // 创建两个Person对象,它们的id分别是101和102。  
        Person p1 = new Person(101);  
        Person p2 = new Person(102);  
        // 新建AtomicReference对象,初始化它的值为p1对象  
        AtomicReference ar = new AtomicReference(p1);  
        // 通过CAS设置ar。如果ar的值为p1的话,则将其设置为p2。  
        ar.compareAndSet(p1, p2);  
  
        Person p3 = (Person)ar.get();  
        System.out.println("p3 is "+p3);  
        System.out.println("p3.equals(p1)="+p3.equals(p1));  
    }  

运行结果:
p3 is id:102
p3.equals(p1)=false

结果说明:
新建AtomicReference对象ar时,将它初始化为p1。
紧接着,通过CAS函数对它进行设置。如果ar的值为p1的话,则将其设置为p2。
最后,获取ar对应的对象,并打印结果。p3.equals(p1)的结果为false,这是因为Person并没有覆盖equals()方法,而是采用继承自Object.java的equals()方法;而Object.java中的equals()实际上是调用"=="去比较两个对象,即比较两个对象的地址是否相等。

相关文章

  • Java 多线程三大核心

    目录:一、 原子性二、可见性三、顺序性 一、 原子性 Java 的原子性就和数据库事务的原子性差不多,一个操作中要...

  • Java 中的volatile 关键字

    并发编程的三个特性 原子性 有序性 可见性 Java 中的volatile 关键字能保证可见性和有序性,但是无法保...

  • Java中Volatile关键字详解

    一、基本概念 先补充一下概念:Java 内存模型中的可见性、原子性和有序性。 可见性: 可见性是一种复杂的属性,因...

  • 22,线程9-Volatile关键字

    一、基本概念 先补充一下概念:Java 内存模型中的可见性、原子性和有序性。 可见性: 可见性是一种复杂的属性,因...

  • Java中Volatile关键字详解(转)

    Java中Volatile关键字详解 一、基本概念 先补充一下概念:Java 内存模型中的可见性、原子性和有序性。...

  • volatile关键字

    Java 内存模型中的可见性、原子性和有序性。 可见性:可见性,是指线程之间的可见性,一个线程修改的状态对另一个线...

  • Java并发学习之synchronized(一)

    synchronized 具有原子性,可见性。原子性:由java内存模型来直接保证的原子性变量操作包括read,l...

  • Java中的原子性和可见性

    原子性:在java语言原子性是指的一个不可以分割的操作,比如说 a = 0,这个就具有原子性,如果是a++, 这个...

  • 面试复习之Java知识解答

    Java知识复习解答 1.synchronize 和 volitale的区别;什么是可见性和原子性 可见性:当一个...

  • JDK 源码解析 —— Java 内存模型

    Java 内存模型是围绕着在并发过程中如何处理原子性、 可见性和有序性来建立的。 原子性:操作不可再分。 如在 J...

网友评论

      本文标题:Java中的原子性和可见性

      本文链接:https://www.haomeiwen.com/subject/aoqsmxtx.html