链接:https://www.jianshu.com/p/882d0e2c3ea6 來源:简书  作者:专职跑龙套

AtomicReference

An object reference that may be updated atomically.

The AtomicReference class provides reference objects that may be read and written atomically, so when multiple threads try to reach them at the same time, only one will be able to do so.
提供了引用变量的读写原子性操作。

提供了如下的方法:

  • compareAndSet(V expect, V update):Atomically sets the value to the given updated value if the current value == the expected value.
  • getAndSet(V newValue):Atomically sets to the given value and returns the old value.
  • lazySet(V newValue):Eventually sets to the given value.
  • set(V newValue):Sets to the given value.
  • get():Gets the current value.

假设有一个类 Person,定义如下:

class Person {
private String name;
private int age; public Person(String name, int age) {
this.name = name;
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String toString() {
return "[name: " + this.name + ", age: " + this.age + "]";
}
}

如果使用普通的对象引用,在多线程情况下进行对象的更新可能会导致不一致性。例如:
一个对象的初始状态为 name=Tom, age = 18
在 线程1 中将 name 修改为 Tom1age + 1
在 线程2 中将 name 修改为 Tom2age + 2

我们认为只会产生两种结果:

  • 若 线程1 先执行,线程2 后执行,则中间状态为 name=Tom1, age = 19,结果状态为 name=Tom2, age = 21
  • 若 线程2 先执行,线程1 后执行,则中间状态为 name=Tom2, age = 20,结果状态为 name=Tom1, age = 21

但是可能的输出如下:

Person is [name: Tom, age: 18]
Thread2 Values [name: Tom1, age: 21]
Thread1 Values [name: Tom1, age: 21]
Now Person is [name: Tom1, age: 21]

// 普通引用
private static Person person; public static void main(String[] args) throws InterruptedException {
person = new Person("Tom", 18); System.out.println("Person is " + person.toString()); Thread t1 = new Thread(new Task1());
Thread t2 = new Thread(new Task2()); t1.start();
t2.start(); t1.join();
t2.join(); System.out.println("Now Person is " + person.toString());
} static class Task1 implements Runnable {
public void run() {
person.setAge(person.getAge() + 1);
person.setName("Tom1"); System.out.println("Thread1 Values "
+ person.toString());
}
} static class Task2 implements Runnable {
public void run() {
person.setAge(person.getAge() + 2);
person.setName("Tom2"); System.out.println("Thread2 Values "
+ person.toString());
}
}

如果使用原子性对象引用,在多线程情况下进行对象的更新可以确保一致性。例如:

// 普通引用
private static Person person;
// 原子性引用
private static AtomicReference<Person> aRperson; public static void main(String[] args) throws InterruptedException {
person = new Person("Tom", 18);
aRperson = new AtomicReference<Person>(person); System.out.println("Atomic Person is " + aRperson.get().toString()); Thread t1 = new Thread(new Task1());
Thread t2 = new Thread(new Task2()); t1.start();
t2.start(); t1.join();
t2.join(); System.out.println("Now Atomic Person is " + aRperson.get().toString());
} static class Task1 implements Runnable {
public void run() {
aRperson.getAndSet(new Person("Tom1", aRperson.get().getAge() + 1)); System.out.println("Thread1 Atomic References "
+ aRperson.get().toString());
}
} static class Task2 implements Runnable {
public void run() {
aRperson.getAndSet(new Person("Tom2", aRperson.get().getAge() + 2)); System.out.println("Thread2 Atomic References "
+ aRperson.get().toString());
}
}

但是可能的输出如下:

Atomic Person is [name: Tom, age: 18]
Thread1 Atomic References [name: Tom1, age: 19]
Thread2 Atomic References [name: Tom2, age: 21]
Now Atomic Person is [name: Tom2, age: 21]


引用:
Java AtomicReference Example

(转)Java 原子性引用 AtomicReference的更多相关文章

  1. Java 原子性引用 AtomicReference

    http://www.jianshu.com/p/882d0e2c3ea6 实现 原子操作 使用场景: 一个线程使用student对象,另一个线程负责定时读表,更新这个对象.那么就可以用AtomicR ...

  2. CAS导致的ABA问题及解决:时间戳原子引用AtomicReference、AtomicStampedReference

    1.CAS导致ABA问题: CAS算法实现一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并交换,那么在这个时间差中会导致数据的变化. 比如:线程1从内存位置V中取出A,这时线程2也从V中取出A ...

  3. java强引用、软引用、弱引用、虚引用

    前言概述 在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象.这就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它,否则就把它扔到垃圾箱,由清洁工人收走 ...

  4. Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针

    Atitit java方法引用(Method References) 与c#委托与脚本语言js的函数指针   1.1. java方法引用(Method References) 与c#委托与脚本语言js ...

  5. java 它 引用(基本类型的包装,构造函数和析构函数c++不同)

      一个:java 和c++参考控制 他提到引用,我们会想到java它不喜欢c++里面的指针.当然java内引用和c++里面的引用是不同的. 比如: 比方C++中,我对某一个函数的声明.int a(i ...

  6. Java Object 引用传递和值传递

    Java Object 引用传递和值传递 @author ixenos Java没有引用传递: 除了在将参数传递给方法(或函数)的时候是"值传递",传递对象引用的副本,在任何用&q ...

  7. Java的引用c++的引用和C指针的区别

    Java的引用本质上就是C中的指针,而c++的引用则完全不同:有一个类 class Point { int x; int y;} 同样的一个Point p; 在Java中p表示一个引用,它等同于C语言 ...

  8. java的引用数据类型,你知道吗???

    有些人很清楚java的八种基本数据类型,但说到java的引用数据类型就不清楚了. Java的数据类型分为两大类,即基本数据类型和引用数据类型,在基本数据类型中有8种 基本数据类型(逻辑型-boolea ...

  9. Java强引用、软引用、弱引用及虚引用深入探讨

    强引用.软引用.弱引用和虚引用深入探讨 为了更灵活的控制对象的生命周期,在JDK1.2之后,引用被划分为强引用.软引用.弱引用.虚引用四种类型,每种类型有不同的生命周期,它们不同的地方就在于垃圾回收器 ...

随机推荐

  1. SQL Server 分页语句查询

    --查询第10页的数据(15条) SELECT TEMP1.* FROM( SELECT TOP 15 ROW_NUMBER() OVER(ORDER BY ID ASC) AS ROWID,* FR ...

  2. ScoutSuite:一款针对云集群环境的安全审计工具

    工具介绍 Scout Suite是一款针对云集群环境的开源安全审计工具,主要针对的是云端环境的安全状况.通过使用云服务提供商暴露的API,Scout Suite可以从高安全风险区域收集配置数据以备研究 ...

  3. 微信小程序这一块(中)

    1.if语句跟for循环的使用 <block wx:if="{{n==1}}"> <view>1917</view> </block> ...

  4. 【报错】Validation failed for object='userLogin'. Error count: 1

    提交表单之后: Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing ...

  5. ELK日志分析系统之elasticsearch7.x最新版安装与配置

    1.Elasticsearch 1.1.elasticsearch的简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful ...

  6. Scala函数高级操作

    字符串高级操作:***** 非常重要 将函数赋值给变量/值def sayHello(name:String): Unit = { println(s"Hello:$name")} ...

  7. 小Z的袜子(题解)(莫队)

    小Z的袜子(题解)(莫队) Junlier良心莫队 题目 luoguP1494 [国家集训队]小Z的袜子 code #include<bits/stdc++.h> #define lst ...

  8. Springboot-技术专区-war包部署在Tomcat上并修改默认端口

    springboot项目内置Tomcat,直接打成jar包在dos下运行即可,但有时我们需要用war包以非内嵌Tomcat的方式来部署,以下是本人的实际经验 1.首先需要修改pom.xml文件 < ...

  9. A星寻路

    逻辑代码 using System.Collections.Generic; using System.Text; using UnityEngine; namespace Game { public ...

  10. C语言文件读写操作

    C语言实现文件读写,注意区分几个方法: 写入: fwrite() //个人认为这个最好,可是实现写入任何数据类型,任何长度 fputs() //写入一个字符串,字符串长度不能太长,具体的长度未知,但估 ...