im钱包App官网最新版下载
数字资产服务平台

im钱包App官网最新版下载是全球著名的数字资产交易平台之一,主要面向全球用户提供比特币、莱特币、以太币等数字资产的币币和衍生品交易服务。

imtoken钱包下载官网苹果|atomiclong

时间:2024-03-17 02:24:12

java多线程之AtomicLong原子类(JDK8) - 掘金

java多线程之AtomicLong原子类(JDK8) - 掘金

首页 首页

沸点

课程

直播

活动

竞赛

商城

APP

插件 搜索历史

清空

创作者中心

写文章 发沸点 写笔记 写代码 草稿箱 创作灵感

查看更多

会员

登录

注册

java多线程之AtomicLong原子类(JDK8)

夏夜凉月

2021-10-26

1,049

引言

有的同学可能会问这个问题,有了Long类型,为什么还要弄一个AtomicLong类出来?因为在32位的操作系统中,64位的Long类型变量会被jvm拆分为两个32位的来操作,因此不具备原子性。而AtomicLong类型可以保证原子性。

1、AtomicLong介绍

AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似。本章以JDK8为版本对AtomicLong基本类型的原子类进行介绍。AtomicLong继承Number抽象类,实现了Serializable接口,操作是线程安全的。

2、分析源码

// 构造函数

AtomicLong()

// 创建值为initialValue的AtomicLong对象

AtomicLong(long initialValue)

// 以原子方式设置当前值为newValue。

final void set(long newValue)

// 获取当前值

final long get()

// 以原子方式将当前值减 1,并返回减1后的值。等价于“--num”

final long decrementAndGet()

// 以原子方式将当前值减 1,并返回减1前的值。等价于“num--”

final long getAndDecrement()

// 以原子方式将当前值加 1,并返回加1后的值。等价于“++num”

final long incrementAndGet()

// 以原子方式将当前值加 1,并返回加1前的值。等价于“num++”

final long getAndIncrement()

// 以原子方式将delta与当前值相加,并返回相加后的值。

final long addAndGet(long delta)

// 以原子方式将delta添加到当前值,并返回相加前的值。

final long getAndAdd(long delta)

// 如果当前值 == expect,则以原子方式将该值设置为update。成功返回true,否则返回false,并且不修改原值。

final boolean compareAndSet(long expect, long update)

// 以原子方式设置当前值为newValue,并返回旧值。

final long getAndSet(long newValue)

//以下部分省略……

AtomicLong的方法都比较简单,下面重点分析下incrementAndGet的方法

public final long incrementAndGet() {

return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L;

}

//unsafe中getAndAddLong实现

public final long getAndAddLong(Object var1, long var2, long var4) {

long var6;

do {

//这个this表示了当前对象的地址,后面的valueOffset是在该对象开始的位置加上这个valueOffset的偏移量,就能拿到的是当前对象的值

var6 = this.getLongVolatile(var1, var2);

} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

return var6;

}

在getAndAddLong实现中,compareAndSwapLong基于的是CPU 的 CAS指令来实现的,可认为是无阻塞的,一个线程的失败或挂起不会引起其它线程也失败或挂起。但并发量很大的话,cpu会花费大量的时间在试错上面,相当于一个自旋的操作。如果并发量小的情况,这些消耗可以忽略不计。

JDK8中新增了LongAdder,内部的实现有点类似ConcurrentHashMap的分段锁,最好的情况下,每个线程都有独立的计数器,这样可以大量减少并发操作。

3、性能测试

下面通过JMH比较一下AtomicLong 和 LongAdder的性能

@OutputTimeUnit(TimeUnit.MICROSECONDS)

@BenchmarkMode(Mode.AverageTime)

public class AtomicLongTest {

private static AtomicLong count = new AtomicLong();

private static LongAdder longAdder = new LongAdder();

public static void main(String[] args) throws Exception {

Options options = new OptionsBuilder().include(AtomicLongTest.class.getName()).forks(1).build();

new Runner(options).run();

}

@Benchmark

@Threads(10)

public void run0(){

count.getAndIncrement();

}

@Benchmark

@Threads(10)

public void run1(){

longAdder.increment();

}

}

maven的pom文件依赖包

org.openjdk.jmh

jmh-core

1.21

org.openjdk.jmh

jmh-generator-annprocess

1.21

1、设置BenchmarkMode为Mode.Throughput,测试吞吐量

2、设置BenchmarkMode为Mode.AverageTime,测试平均耗时

3、程序运行直接使用run方法,不支持debug模式

下面是运行的结果:

吞吐量

Benchmark Mode Cnt Score Error Units

AtomicLongTest.run0 thrpt 5 34.070 ± 1.830 ops/us

AtomicLongTest.run1 thrpt 5 152.216 ± 45.756 ops/us

平均耗时

Benchmark Mode Cnt Score Error Units

AtomicLongTest.run0 avgt 5 0.350 ± 0.063 us/op

AtomicLongTest.run1 avgt 5 0.072 ± 0.029 us/op

从上面可以看出LongAdder的吞吐量和平均耗时均优于AtomicLong

4、总结

普通场景保证线程安全,建议使用AtomicLong,一些高并发的场景,比如限流计数器,建议使用LongAdder替换AtomicLong,以提高性能。

结束语

本篇介绍了AtomicLong的基本原理,比较了LongAdder和AtomicLong之间高并发下的性能,还介绍了一款适合java的JMH性能测试工具,有兴趣的同学可以详细的了解下,下一章将介绍JUC包中的锁。

如果你觉得本篇文章对你有帮助的话,请帮忙点个赞,再加一个关注。

夏夜凉月

Java开发工程师

40

文章

6.7k

阅读

2

粉丝 目录 收起

引言

1、AtomicLong介绍

2、分析源码

3、性能测试

4、总结

结束语

友情链接:

下面算法将一维数组a中n个逆序

AtomicLong (Java Platform SE 8 )

AtomicLong (Java Platform SE 8 )

JavaScript is disabled on your browser.

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Java™ PlatformStandard Ed. 8

Prev Class

Next Class

Frames

No Frames

All Classes

Summary: 

Nested | 

Field | 

Constr | 

Method

Detail: 

Field | 

Constr | 

Method

compact1, compact2, compact3

java.util.concurrent.atomic

Class AtomicLong

java.lang.Object

java.lang.Number

java.util.concurrent.atomic.AtomicLong

All Implemented Interfaces:

Serializable

public class AtomicLong

extends Number

implements Serializable

A long value that may be updated atomically. See the

java.util.concurrent.atomic package specification for

description of the properties of atomic variables. An

AtomicLong is used in applications such as atomically

incremented sequence numbers, and cannot be used as a replacement

for a Long. However, this class does extend

Number to allow uniform access by tools and utilities that

deal with numerically-based classes.

Since:

1.5

See Also:

Serialized Form

Constructor Summary

Constructors 

Constructor and Description

AtomicLong()

Creates a new AtomicLong with initial value 0.

AtomicLong(long initialValue)

Creates a new AtomicLong with the given initial value.

Method Summary

All Methods Instance Methods Concrete Methods 

Modifier and Type

Method and Description

long

accumulateAndGet(long x,

LongBinaryOperator accumulatorFunction)

Atomically updates the current value with the results of

applying the given function to the current and given values,

returning the updated value.

long

addAndGet(long delta)

Atomically adds the given value to the current value.

boolean

compareAndSet(long expect,

long update)

Atomically sets the value to the given updated value

if the current value == the expected value.

long

decrementAndGet()

Atomically decrements by one the current value.

double

doubleValue()

Returns the value of this AtomicLong as a double

after a widening primitive conversion.

float

floatValue()

Returns the value of this AtomicLong as a float

after a widening primitive conversion.

long

get()

Gets the current value.

long

getAndAccumulate(long x,

LongBinaryOperator accumulatorFunction)

Atomically updates the current value with the results of

applying the given function to the current and given values,

returning the previous value.

long

getAndAdd(long delta)

Atomically adds the given value to the current value.

long

getAndDecrement()

Atomically decrements by one the current value.

long

getAndIncrement()

Atomically increments by one the current value.

long

getAndSet(long newValue)

Atomically sets to the given value and returns the old value.

long

getAndUpdate(LongUnaryOperator updateFunction)

Atomically updates the current value with the results of

applying the given function, returning the previous value.

long

incrementAndGet()

Atomically increments by one the current value.

int

intValue()

Returns the value of this AtomicLong as an int

after a narrowing primitive conversion.

void

lazySet(long newValue)

Eventually sets to the given value.

long

longValue()

Returns the value of this AtomicLong as a long.

void

set(long newValue)

Sets to the given value.

String

toString()

Returns the String representation of the current value.

long

updateAndGet(LongUnaryOperator updateFunction)

Atomically updates the current value with the results of

applying the given function, returning the updated value.

boolean

weakCompareAndSet(long expect,

long update)

Atomically sets the value to the given updated value

if the current value == the expected value.

Methods inherited from class java.lang.Number

byteValue, shortValue

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

Constructor Detail

AtomicLong

public AtomicLong(long initialValue)

Creates a new AtomicLong with the given initial value.

Parameters:

initialValue - the initial value

AtomicLong

public AtomicLong()

Creates a new AtomicLong with initial value 0.

Method Detail

get

public final long get()

Gets the current value.

Returns:

the current value

set

public final void set(long newValue)

Sets to the given value.

Parameters:

newValue - the new value

lazySet

public final void lazySet(long newValue)

Eventually sets to the given value.

Parameters:

newValue - the new value

Since:

1.6

getAndSet

public final long getAndSet(long newValue)

Atomically sets to the given value and returns the old value.

Parameters:

newValue - the new value

Returns:

the previous value

compareAndSet

public final boolean compareAndSet(long expect,

long update)

Atomically sets the value to the given updated value

if the current value == the expected value.

Parameters:

expect - the expected value

update - the new value

Returns:

true if successful. False return indicates that

the actual value was not equal to the expected value.

weakCompareAndSet

public final boolean weakCompareAndSet(long expect,

long update)

Atomically sets the value to the given updated value

if the current value == the expected value.

May fail

spuriously and does not provide ordering guarantees, so is

only rarely an appropriate alternative to compareAndSet.

Parameters:

expect - the expected value

update - the new value

Returns:

true if successful

getAndIncrement

public final long getAndIncrement()

Atomically increments by one the current value.

Returns:

the previous value

getAndDecrement

public final long getAndDecrement()

Atomically decrements by one the current value.

Returns:

the previous value

getAndAdd

public final long getAndAdd(long delta)

Atomically adds the given value to the current value.

Parameters:

delta - the value to add

Returns:

the previous value

incrementAndGet

public final long incrementAndGet()

Atomically increments by one the current value.

Returns:

the updated value

decrementAndGet

public final long decrementAndGet()

Atomically decrements by one the current value.

Returns:

the updated value

addAndGet

public final long addAndGet(long delta)

Atomically adds the given value to the current value.

Parameters:

delta - the value to add

Returns:

the updated value

getAndUpdate

public final long getAndUpdate(LongUnaryOperator updateFunction)

Atomically updates the current value with the results of

applying the given function, returning the previous value. The

function should be side-effect-free, since it may be re-applied

when attempted updates fail due to contention among threads.

Parameters:

updateFunction - a side-effect-free function

Returns:

the previous value

Since:

1.8

updateAndGet

public final long updateAndGet(LongUnaryOperator updateFunction)

Atomically updates the current value with the results of

applying the given function, returning the updated value. The

function should be side-effect-free, since it may be re-applied

when attempted updates fail due to contention among threads.

Parameters:

updateFunction - a side-effect-free function

Returns:

the updated value

Since:

1.8

getAndAccumulate

public final long getAndAccumulate(long x,

LongBinaryOperator accumulatorFunction)

Atomically updates the current value with the results of

applying the given function to the current and given values,

returning the previous value. The function should be

side-effect-free, since it may be re-applied when attempted

updates fail due to contention among threads. The function

is applied with the current value as its first argument,

and the given update as the second argument.

Parameters:

x - the update value

accumulatorFunction - a side-effect-free function of two arguments

Returns:

the previous value

Since:

1.8

accumulateAndGet

public final long accumulateAndGet(long x,

LongBinaryOperator accumulatorFunction)

Atomically updates the current value with the results of

applying the given function to the current and given values,

returning the updated value. The function should be

side-effect-free, since it may be re-applied when attempted

updates fail due to contention among threads. The function

is applied with the current value as its first argument,

and the given update as the second argument.

Parameters:

x - the update value

accumulatorFunction - a side-effect-free function of two arguments

Returns:

the updated value

Since:

1.8

toString

public String toString()

Returns the String representation of the current value.

Overrides:

toString in class Object

Returns:

the String representation of the current value

intValue

public int intValue()

Returns the value of this AtomicLong as an int

after a narrowing primitive conversion.

Specified by:

intValue in class Number

Returns:

the numeric value represented by this object after conversion

to type int.

See The Java™ Language Specification:

5.1.3 Narrowing Primitive Conversions

longValue

public long longValue()

Returns the value of this AtomicLong as a long.

Specified by:

longValue in class Number

Returns:

the numeric value represented by this object after conversion

to type long.

floatValue

public float floatValue()

Returns the value of this AtomicLong as a float

after a widening primitive conversion.

Specified by:

floatValue in class Number

Returns:

the numeric value represented by this object after conversion

to type float.

See The Java™ Language Specification:

5.1.2 Widening Primitive Conversions

doubleValue

public double doubleValue()

Returns the value of this AtomicLong as a double

after a widening primitive conversion.

Specified by:

doubleValue in class Number

Returns:

the numeric value represented by this object after conversion

to type double.

See The Java™ Language Specification:

5.1.2 Widening Primitive Conversions

Skip navigation links

Overview

Package

Class

Use

Tree

Deprecated

Index

Help

Java™ PlatformStandard Ed. 8

Prev Class

Next Class

Frames

No Frames

All Classes

Summary: 

Nested | 

Field | 

Constr | 

Method

Detail: 

Field | 

Constr | 

Method

Submit a bug or feature For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. Copyright © 1993, 2024, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. Also see the documentation redistribution policy.

Scripting on this page tracks web page traffic, but does not change the content in any way.

Java原子类AtomicLong的用法_atomiclong相加-CSDN博客

>

Java原子类AtomicLong的用法_atomiclong相加-CSDN博客

Java原子类AtomicLong的用法

最新推荐文章于 2022-10-31 09:00:00 发布

木凡空

最新推荐文章于 2022-10-31 09:00:00 发布

阅读量4.2k

收藏

4

点赞数

分类专栏:

Java

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/zengxingyuluo/article/details/105607450

版权

Java

专栏收录该内容

13 篇文章

0 订阅

订阅专栏

1、AtomicLong可理解为加了synchronized的long

2、AtomicLong函数:

// 构造函数

AtomicLong()

// 创建值为initialValue的AtomicLong对象

AtomicLong(long initialValue)

// 以原子方式设置当前值为newValue。

final void set(long newValue)

// 获取当前值

final long get()

// 以原子方式将当前值减 1,并返回减1后的值。等价于“--num”

final long decrementAndGet()

// 以原子方式将当前值减 1,并返回减1前的值。等价于“num--”

final long getAndDecrement()

// 以原子方式将当前值加 1,并返回加1后的值。等价于“++num”

final long incrementAndGet()

// 以原子方式将当前值加 1,并返回加1前的值。等价于“num++”

final long getAndIncrement()

// 以原子方式将delta与当前值相加,并返回相加后的值。

final long addAndGet(long delta)

// 以原子方式将delta添加到当前值,并返回相加前的值。

final long getAndAdd(long delta)

// 如果当前值 == expect,则以原子方式将该值设置为update。成功返回true,否则返回false,并且不修改原值。

final boolean compareAndSet(long expect, long update)

// 以原子方式设置当前值为newValue,并返回旧值。

final long getAndSet(long newValue)

// 返回当前值对应的int值

int intValue()

// 获取当前值对应的long值

long longValue()

// 以 float 形式返回当前值

float floatValue()

// 以 double 形式返回当前值

double doubleValue()

// 最后设置为给定值。延时设置变量值,这个等价于set()方法,但是由于字段是volatile类型的,因此次字段的修改会比普通字段(非volatile字段)有稍微的性能延时(尽管可以忽略),所以如果不是想立即读取设置的新值,允许在“后台”修改值,那么此方法就很有用。如果还是难以理解,这里就类似于启动一个后台线程如执行修改新值的任务,原线程就不等待修改结果立即返回(这种解释其实是不正确的,但是可以这么理解)。

final void lazySet(long newValue)

// 如果当前值 == 预期值,则以原子方式将该设置为给定的更新值。JSR规范中说:以原子方式读取和有条件地写入变量但不 创建任何 happen-before 排序,因此不提供与除 weakCompareAndSet 目标外任何变量以前或后续读取或写入操作有关的任何保证。大意就是说调用weakCompareAndSet时并不能保证不存在happen-before的发生(也就是可能存在指令重排序导致此操作失败)。但是从Java源码来看,其实此方法并没有实现JSR规范的要求,最后效果和compareAndSet是等效的,都调用了unsafe.compareAndSwapInt()完成操作。

final boolean weakCompareAndSet(long expect, long update)

3、使用

AtomicLong a = new AtomicLong(1L);

AtomicLong b = new AtomicLong(2L);

//相加

a.addAndGet(b.longValue())

 

优惠劵

木凡空

关注

关注

0

点赞

4

收藏

觉得还不错?

一键收藏

知道了

0

评论

Java原子类AtomicLong的用法

1、AtomicLong可理解为加了synchronized的long2、AtomicLong函数:// 构造函数AtomicLong()// 创建值为initialValue的AtomicLong对象AtomicLong(long initialValue)// 以原子方式设置当前值为newValue。final void set(long newValue) // 获取当...

复制链接

扫一扫

专栏目录

Java concurrency之AtomicLong原子类_动力节点Java学院整理

08-30

AtomicLong是作用是对长整形进行原子操作。下面通过本文给大家介绍Java concurrency之AtomicLong原子类的相关知识,感兴趣的朋友一起看看吧

java 原子long_Java原子类--AtomicLong

weixin_39630182的博客

02-13

2046

AtomicLong介绍和函数列表AtomicLong是作用是对长整形进行原子操作。在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。AtomicLong函数列表// 构造函数AtomicLong()// 创建值为initialValue的AtomicLong对象Ato...

参与评论

您还未登录,请先

登录

后发表或查看评论

Java concurrency之AtomicLongArray原子类_动力节点Java学院整理

03-19

Java concurrency之AtomicLongArray原子类_动力节点Java学院整理,动力节点口口相传的Java黄埔军校

java编发编程:JUC综合讲解

最新发布

08-09

Java 并发编程在现代软件开发中占据重要地位,尤其是在多核处理器的时代。JUC(java.util.concurrent)库是 Java 标准库的一部分,提供了丰富的多线程并发工具,旨在帮助开发者编写高性能、高可伸缩性的并发程序。下面综合介绍 JUC 库的几个核心概念以及它们在并发编程中的重要性。

1. 线程池(ThreadPoolExecutor):

线程池是 JUC 中最重要的组件之一,它解决了频繁创建和销毁线程所带来的性能开销问题。

2. 并发集合类(Concurrent Collections):

JUC 提供了线程安全的并发集合类,如 ConcurrentHashMap、ConcurrentLinkedQueue 等。

3. 原子操作(Atomic Operations):

原子操作是不可再分割的基本操作,JUC 提供了一系列原子操作类,如 AtomicInteger、AtomicLong 等。

4. 同步器(Synchronizers):JUC 中的同步器主要通过 AQS(AbstractQueuedSynchronizer)提供支持。

Java并发学习-AtomicIntegerFieldUpdater字段原子更新类.docx

06-26

What is AtomicIntegerFieldUpdater

相信前言部分讲的已经很清晰易懂了,AtomicIntegerFieldUpdater就是用来更新某一个实例对象里面的int属性的。

但是注意,在用法上有规则:

字段必须是volatile类型的,在线程之间共享变量时保证立即可见

字段的描述类型( 修饰符public/protected/default/private )是与调用者与操作对象字段的关系一致。 也就是说调用者能够直接操作对象字段 ,那么就可以反射进行原子操作。

对于父类的字段,子类是不能直接操作的,尽管子类可以访问父类的字段。

只能是实例变量,不能是类变量,也就是说不能加static关键字。

只能是可修改变量,不能使final变量,因为final的语义就是不可修改。

对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段,不能修改其包装类型(Integer/Long)。如果要修改包装类型就需要使用AtomicReferenceFieldUpdater。

AtomicLong

lzc_23的博客

05-10

650

本文翻译自http://tutorials.jenkov.com/java-util-concurrent/atomiclong.html,人工翻译,仅供学习交流。

AtomicLong

AtomicLong类为您提供了一个Long变量,它可以原子地读写。它也包含像compareAndSet()这样的高级原子操作。AtomicLong类位于java.util.concurrent.atomic包中,因此完整的类名java.util.concurrent.atomic.AtomicLong。本文描述了在Jav

原子操作类AtomicLong、LongAdder、LongAccumulator

qq_44300280的博客

10-31

639

1. 原子操作类

1.1 原子操作类概述

1.2 分类

1.2.1 基本类型原子类

1.2.2 数组类型原子类

1.2.3 引用类型原子类

1.2.4 对象的属性修改原子类

1.2.5 原子操作增强类原理深度解析

AtomicLong 原子操作

SongYuxinIT的博客

08-30

505

AtomicLong是作用是对长整形进行原子操作。

在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。

创建具有初始值 0 的新 AtomicLong

private AtomicLong sendCount = new AtomicLong(0);

创建具有给定初始值10的新 AtomicLong

private AtomicLong sendCount10 = .

Java原子类:AtomicLong、LongAdder、LongAccumulator详解

li_w_ch的博客

01-12

1123

JUC包提供了一系列的原子性操作类,这些类都是使用非阻塞算法CAS实现的,相比使用锁实现原子性操作,这在性能上有很大的提高。

1、AtomicLong

JUC并发包中包含有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们的原理类似。AtomicLong是原子性递增或者递减类,其内部使用Unsafe来实现。

多线程使用AtomicLong统计0的个数:

// 统计0的个数

public class Atomic {

// 创建Long型原子计数

并发编程 — 原子类 AtomicLong 详解

small_love的专栏

12-12

948

与AtomicInteger非常类似,AtomicLong提供了原子性操作long类型数据的解决方案,AtomicLong所提供的原子性方法在使用习惯上也与AtomicInteger非常一致。我们不再详细解释每一个方法如何使用,可以参考 《AtomicInteger》 。AtomicInteger类中最为关键的方法为compareAndSwapInt,同样,在AtomicLong类中也提供了类似的方法compareAndSwapLong,但是该方法要比compareAndSwapInt复杂很多。

我们知道

原子类型:AtomicLong详解

wyaoyao93的博客

04-19

2667

与AtomicInteger非常类似,AtomicLong提供了原子性操作long类型数据的解决方案,AtomicLong同样也继承自Number类,AtomicLong所提供的原子性方法在使用习惯上也与AtomicInteger非常一致。

这里就不多介绍

1 compareAndSwapLong和compareAndSwapInt

AtomicInteger类中最为关键的方法为compareAndSwapInt,同样,在AtomicLong类中也提供了类似的方法compareAndSwapLong,但是该

Java多线程之JUC原子类AtomicLong

weixin_33728268的博客

07-25

82

2019独角兽企业重金招聘Python工程师标准>>>

...

AtomicLong和LongAdder

weixin_50391597的博客

03-09

207

AtomicLong是1.5实现的long类型的原子类

long getAndIncrement(); (自增,不会保证原子性)long incrementAndGet(); (自增,保证原子性)long decrementAndGet();(自减,保证原子性)long getAndDecrement();(自减,不会保证原子性)

long addAndGet(long delta); (加法,保证原子性)

long getAndAdd(long delta); (加法,不会保证原...

“全栈2019”Java原子操作第七章:AtomicLong介绍与使用

人人都是程序员官方博客

06-06

269

难度

初级

学习时间

10分钟

适合人群

零基础

开发语言

Java

开发环境

JDK v11

IntelliJ IDEA v2018.3

文章原文链接

“全栈2019”Java原子操作第七章:AtomicLong介绍与使用

下一章

“全栈2019”Java原子操作第八章:AtomicReference介绍与使用

学习小组

加入同步学习小组,共同交流与进步。

方式一:加入编程圈子。

方...

高并发编程:AtomicLong

Sq2494361212的博客

06-25

180

一、AtomicLong介绍

AtomicLong是作用是对长整形进行原子操作

二、为什么是AtomicLong而不是Long

atomiclong 可以理解是加了synchronized的long

在多线程开发中普通的Long非原子性操作对出现安全问题

如果赋值一个long变量,编译后,会产生多个JVM语言指令,所以不具有原子性。

当一个线程正在操作一个原子变量时,即使其他线程也想要操作这个变量,类的实现中含有一个检查那步骤操作是否完成的机制。 基本上,操作获取变量的值,改变本地变量值,然后尝试以新值代替

AtomicLong和LongAdder的区别

weixin_30756499的博客

11-29

45

AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的。

LongAdder在AtomicLong的基础上将单点的更新压力分散到各个节点,在低并发的时候通过对base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并发的时候通过分散提高了性能。 缺点是LongAdder在统计的...

AtomicLong使用

大鸡腿的博客

01-30

1543

Long64位置,会被分成2段进行储存,不安全。所以使用ActomicLong保证原子性

下面介绍下使用方法

AtomicLong atomicLong=new AtomicLong(100);

新建一个初始值为100的,如果要获得值调用get()方法

如果需要++操作,调用incrementAndGet()

atomiclong.get()获取值

...

LongAdder和AtomicLong的区别

不羁朔风的博客

11-10

1344

AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用自循(CLH)方式不断地cas到特定的值,从而达到更新数据的目的。然而在线程竞争激烈的情况下,自循往往浪费很多计算资源才能达成预期效果。

 

面对自循的缺点,jdk1.8推出了LongAdder类,他的实现方式有点像ConcurrentHashMap一样,采用空间换时间的方式,提高在线程竞争激烈的...

为什么要使用atomiclong 而不是 long

优秀的判断力来自经验,但经验来自于错误的判断

08-07

5752

一、首先你得了解synchronized(同步锁),atomiclong 可以理解是加了synchronized的long。

二、现在我们思考一下使用atomiclong 这个场景,必然是跟多线程有关,而且可能用于编写计数器。

三、了解JVM指令的,都知道如果赋值一个long变量,编译后,会产生多个JVM语言指令,如果处于多线程情况下对于这个变量进行加减操作会导致数据不一致。为避免此问题,J...

Java 什么是原子类

07-28

Java中的原子类(Atomic classes)是一组为了支持并发编程而提供的线程安全的类。原子类提供了一些基本的原子操作,这些操作可以在没有锁的情况下进行,保证了操作的原子性。 原子类主要包括以下几个常用的类: 1....

“相关推荐”对你有帮助么?

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

木凡空

CSDN认证博客专家

CSDN认证企业博客

码龄9年

暂无认证

141

原创

5万+

周排名

201万+

总排名

30万+

访问

等级

3350

积分

30

粉丝

110

获赞

19

评论

483

收藏

私信

关注

热门文章

Hive查看表所有分区

51309

启动和退出hive

23762

Android调用天气接口(和风天气)

23430

互联网公司组织架构

23334

Java栈的实现

12692

分类专栏

版本

Hadoop

5篇

Maven

3篇

Spark

14篇

Scala

2篇

SpringBoot

12篇

Redis

2篇

Spring

JavaWeb

1篇

Linux

15篇

Shell

14篇

计算机网络

驾照

DataFrame

1篇

SparkSQL

2篇

RDD

3篇

Vue

11篇

安裝教程

1篇

Windows

5篇

NodeJS

1篇

IDEA

PyCharm

Echarts

1篇

CSS

2篇

HTML

2篇

公司创业

1篇

内网穿透

1篇

FineBI

1篇

大数据分析

1篇

Yapi

1篇

MyBatis

1篇

Nginx

1篇

JMeter

测试工程师

1篇

JavaScript

2篇

BootStrap

1篇

JQuery

2篇

Kafka

SparkMLlib

线性代数

Elasticsearch

SparkStreaming

1篇

LeetCode

3篇

软件工程师

服务器

Python

投资

Zookeeper

1篇

HBase

1篇

Android

2篇

Java

13篇

数据结构与算法

15篇

ACM

3篇

Git

2篇

Hive

4篇

MySQL

9篇

最新评论

前端页面获取后台Controller的Model传值

爱吃鱼的小馋猫:

无效方法

Win10右键菜单添加管理员方式打开cmd

yssokl:

感谢回复

Win10右键菜单添加管理员方式打开cmd

俺要花钱买ID:

runas右键新建一个字符串值,名称为"Icon",数据为"‪C:\Windows\System32\cmd.exe",就能显示cmd图标了

Hive批量删除表分区

I'm a Pirate:

你这只是针对一个表,称不上批量

Kafka的消息丢失和重复消费

最闲程序员:

在二的消息消费中的(1)说法不对吧。。。这个不是针对producer的消息丢失的解决方法吗,并不是消费的丢失解决方法,producer消息丢失解决方案利用的是ack应答机制,而consumer消息丢失的解决方案是关闭自动提交offset,在消息处理完成后,再手动去提交offset

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

MySQL之事务详解

Java多线程详解

Spring面试基础

2020年90篇

2019年35篇

2018年10篇

2017年7篇

目录

目录

分类专栏

版本

Hadoop

5篇

Maven

3篇

Spark

14篇

Scala

2篇

SpringBoot

12篇

Redis

2篇

Spring

JavaWeb

1篇

Linux

15篇

Shell

14篇

计算机网络

驾照

DataFrame

1篇

SparkSQL

2篇

RDD

3篇

Vue

11篇

安裝教程

1篇

Windows

5篇

NodeJS

1篇

IDEA

PyCharm

Echarts

1篇

CSS

2篇

HTML

2篇

公司创业

1篇

内网穿透

1篇

FineBI

1篇

大数据分析

1篇

Yapi

1篇

MyBatis

1篇

Nginx

1篇

JMeter

测试工程师

1篇

JavaScript

2篇

BootStrap

1篇

JQuery

2篇

Kafka

SparkMLlib

线性代数

Elasticsearch

SparkStreaming

1篇

LeetCode

3篇

软件工程师

服务器

Python

投资

Zookeeper

1篇

HBase

1篇

Android

2篇

Java

13篇

数据结构与算法

15篇

ACM

3篇

Git

2篇

Hive

4篇

MySQL

9篇

目录

评论

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

AtomicLong

AtomicLong

JavaScript is disabled on your browser.

跳过导航

概述

模块

软件包

使用

已过时的

索引

帮助

Java SE 11 & JDK 11

所有类

SEARCH:

JavaScript is disabled on your browser.

概要: 

嵌套 | 

字段 | 

构造方法 | 

方法

详细信息: 

字段 | 

构造方法 | 

方法

 

模块 

java.base

软件包 

java.util.concurrent.atomic

Class AtomicLong

java.lang.Object

java.lang.Number

java.util.concurrent.atomic.AtomicLong

实现的所有接口

Serializable

public class AtomicLong

extends Number

implements Serializable

可以原子方式更新的long值。

有关原子访问属性的描述,请参阅VarHandle规范。

AtomicLong用于诸如原子递增序列号的应用中,并且不能用作Long的替代物 。

但是,此类确实扩展了Number以允许通过处理基于数字的类的工具和实用程序进行统一访问。

从以下版本开始:

1.5

另请参见:

Serialized Form

构造方法摘要

构造方法

 

构造器

描述

AtomicLong()

创建一个初始值为

0的新AtomicLong。

AtomicLong​(long initialValue)

使用给定的初始值创建一个新的AtomicLong。

方法摘要

所有方法 

实例方法

具体的方法 

弃用的方法 

变量和类型

方法

描述

long

accumulateAndGet​(long x, LongBinaryOperator accumulatorFunction)

原子更新(具有由

VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值以及将给定函数应用于当前值和给定值的结果,返回更新的值。

long

addAndGet​(long delta)

原子地将给定值添加到当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

long

compareAndExchange​(long expectedValue, long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchange(java.lang.Object...) 。

long

compareAndExchangeAcquire​(long expectedValue, long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchangeAcquire(java.lang.Object...) 。

long

compareAndExchangeRelease​(long expectedValue, long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchangeRelease(java.lang.Object...) 。

boolean

compareAndSet​(long expectedValue, long newValue)

原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.compareAndSet(java.lang.Object...) 。

long

decrementAndGet()

原子地递减当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

double

doubleValue()

返回此的当前值

AtomicLong作为

double加宽原始转换后,通过规定的,具有记忆效果

VarHandle.getVolatile(java.lang.Object...) 。

float

floatValue()

在扩展基元转换后,将此

AtomicLong的当前值返回为

float ,其内存效果由

VarHandle.getVolatile(java.lang.Object...)指定。

long

get()

返回当前值,具有

VarHandle.getVolatile(java.lang.Object...)指定的内存效果。

long

getAcquire()

返回当前值,具有

VarHandle.getAcquire(java.lang.Object...)指定的内存效果。

long

getAndAccumulate​(long x, LongBinaryOperator accumulatorFunction)

原子更新(具有由

VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值以及将给定函数应用于当前值和给定值的结果,返回先前的值。

long

getAndAdd​(long delta)

原子地将给定值添加到当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

long

getAndDecrement()

原子地递减当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

long

getAndIncrement()

以原子方式递增当前值,具有

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

long

getAndSet​(long newValue)

以原子方式将值设置为

newValue并返回旧值,并使用

VarHandle.getAndSet(java.lang.Object...)指定的内存效果。

long

getAndUpdate​(LongUnaryOperator updateFunction)

原子更新(具有由

VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值和应用给定函数的结果,返回先前的值。

long

getOpaque()

返回当前值,具有

VarHandle.getOpaque(java.lang.Object...)指定的内存效果。

long

getPlain()

返回当前值,读取的内存语义就像变量声明为非

volatile 。

long

incrementAndGet()

以原子方式递增当前值,具有

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

int

intValue()

返回此的当前值

AtomicLong作为

int如通过指定一个基本收缩转换之后,与记忆效应

VarHandle.getVolatile(java.lang.Object...) 。

void

lazySet​(long newValue)

将值设置为

newValue ,具有

VarHandle.setRelease(java.lang.Object...)指定的记忆效果。

long

longValue()

返回此的当前值

AtomicLong作为

long如通过指定,记忆效应

VarHandle.getVolatile(java.lang.Object...) 。

void

set​(long newValue)

将值设置为

newValue ,具有

VarHandle.setVolatile(java.lang.Object...)指定的记忆效果。

void

setOpaque​(long newValue)

将值设置为

newValue ,具有

VarHandle.setOpaque(java.lang.Object...)指定的记忆效果。

void

setPlain​(long newValue)

将值设置为

newValue ,设置的内存语义就像变量被声明为非

volatile和非

final 。

void

setRelease​(long newValue)

将值设置为

newValue ,具有

VarHandle.setRelease(java.lang.Object...)指定的记忆效果。

String

toString()

返回当前值的String表示形式。

long

updateAndGet​(LongUnaryOperator updateFunction)

原子更新(具有由

VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值和应用给定函数的结果,返回更新的值。

boolean

weakCompareAndSet​(long expectedValue, long newValue)

已过时。

此方法具有简单的记忆效应,但方法名称意味着易失性记忆效应(请参阅compareAndExchange(long, long)和compareAndSet(long, long)等方法)。

boolean

weakCompareAndSetAcquire​(long expectedValue, long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetAcquire(java.lang.Object...) 。

boolean

weakCompareAndSetPlain​(long expectedValue, long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetPlain(java.lang.Object...) 。

boolean

weakCompareAndSetRelease​(long expectedValue, long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetRelease(java.lang.Object...) 。

boolean

weakCompareAndSetVolatile​(long expectedValue, long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSet(java.lang.Object...) 。

声明方法的类 java.lang.Number byteValue, shortValue

声明方法的类 java.lang.Object clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

构造方法详细信息

AtomicLong public AtomicLong​(long initialValue)

使用给定的初始值创建一个新的AtomicLong。

参数

initialValue - 初始值

AtomicLong public AtomicLong()

创建一个初始值为

0的新AtomicLong。

方法详细信息

get public final long get()

返回当前值,具有

VarHandle.getVolatile(java.lang.Object...)指定的内存效果。

结果

当前的价值

set public final void set​(long newValue)

将值设置为

newValue ,具有

VarHandle.setVolatile(java.lang.Object...)指定的记忆效果。

参数

newValue - 新值

lazySet public final void lazySet​(long newValue)

将值设置为

newValue ,具有

VarHandle.setRelease(java.lang.Object...)指定的记忆效果。

参数

newValue - 新值

从以下版本开始:

1.6

getAndSet public final long getAndSet​(long newValue)

以原子方式将值设置为

newValue并返回旧值,并使用

VarHandle.getAndSet(java.lang.Object...)指定的内存效果。

参数

newValue - 新值

结果

以前的值

compareAndSet public final boolean compareAndSet​(long expectedValue,

long newValue)

原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.compareAndSet(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功。

错误返回表示实际值不等于预期值。

weakCompareAndSet @Deprecated(since="9")

public final boolean weakCompareAndSet​(long expectedValue,

long newValue)

Deprecated.

This method has plain memory effects but the method name implies volatile memory effects (see methods such as

compareAndExchange(long, long) and

compareAndSet(long, long)). To avoid confusion over plain or volatile memory effects it is recommended that the method

weakCompareAndSetPlain(long, long) be used instead.

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetPlain(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功

另请参见:

weakCompareAndSetPlain(long, long)

weakCompareAndSetPlain public final boolean weakCompareAndSetPlain​(long expectedValue,

long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetPlain(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功

从以下版本开始:

9

getAndIncrement public final long getAndIncrement()

以原子方式递增当前值,具有VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

相当于getAndAdd(1) 。

结果

以前的值

getAndDecrement public final long getAndDecrement()

原子地递减当前值,具有由VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

相当于getAndAdd(-1) 。

结果

以前的值

getAndAdd public final long getAndAdd​(long delta)

原子地将给定值添加到当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

参数

delta - 要添加的值

结果

以前的值

incrementAndGet public final long incrementAndGet()

以原子方式递增当前值,具有VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

相当于addAndGet(1) 。

结果

更新的值

decrementAndGet public final long decrementAndGet()

原子地递减当前值,具有由VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

相当于addAndGet(-1) 。

结果

更新的值

addAndGet public final long addAndGet​(long delta)

原子地将给定值添加到当前值,具有由

VarHandle.getAndAdd(java.lang.Object...)指定的记忆效应。

参数

delta - 要添加的值

结果

更新的值

getAndUpdate public final long getAndUpdate​(LongUnaryOperator updateFunction)

原子更新(具有由VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值和应用给定函数的结果,返回先前的值。

该函数应该是无副作用的,因为当尝试的更新由于线程之间的争用而失败时,它可能会被重新应用。

参数

updateFunction - 无副作用的功能

结果

以前的值

从以下版本开始:

1.8

updateAndGet public final long updateAndGet​(LongUnaryOperator updateFunction)

原子更新(具有由VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值和应用给定函数的结果,返回更新的值。

该函数应该是无副作用的,因为当尝试的更新由于线程之间的争用而失败时,它可能会被重新应用。

参数

updateFunction - 无副作用的功能

结果

更新的值

从以下版本开始:

1.8

getAndAccumulate public final long getAndAccumulate​(long x,

LongBinaryOperator accumulatorFunction)

原子更新(具有由VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值以及将给定函数应用于当前值和给定值的结果,返回先前值。

该函数应该是无副作用的,因为当尝试的更新由于线程之间的争用而失败时,它可能会被重新应用。

该函数应用当前值作为其第一个参数,并将给定更新作为第二个参数。

参数

x - 更新值

accumulatorFunction - 两个参数的无副作用函数

结果

以前的值

从以下版本开始:

1.8

accumulateAndGet public final long accumulateAndGet​(long x,

LongBinaryOperator accumulatorFunction)

原子更新(具有由VarHandle.compareAndSet(java.lang.Object...)指定的记忆效应)当前值以及将给定函数应用于当前值和给定值的结果,返回更新的值。

该函数应该是无副作用的,因为当尝试的更新由于线程之间的争用而失败时,它可能会被重新应用。

该函数应用当前值作为其第一个参数,并将给定更新作为第二个参数。

参数

x - 更新值

accumulatorFunction - 两个参数的无副作用函数

结果

更新的值

从以下版本开始:

1.8

toString public String toString()

返回当前值的String表示形式。

重写:

toString在类

Object

结果

当前值的String表示形式

intValue public int intValue()

在缩小基元转换后,返回

AtomicLong的当前值作为

int ,具有由

VarHandle.getVolatile(java.lang.Object...)指定的记忆效应。

Specified by:

intValue在类

Number

结果

转换为类型

int后此对象表示的数值。

See The Java™ Language Specification:

5.1.3缩小原始转换

longValue public long longValue()

返回此的当前值AtomicLong作为long如通过指定,记忆效应VarHandle.getVolatile(java.lang.Object...) 。

相当于get() 。

Specified by:

longValue在类

Number

结果

转换为类型

long后此对象表示的数值。

floatValue public float floatValue()

返回此的当前值

AtomicLong作为

float加宽原始转换后,通过规定的,具有记忆效果

VarHandle.getVolatile(java.lang.Object...) 。

Specified by:

floatValue类

Number

结果

转换为类型

float后此对象表示的数值。

See The Java™ Language Specification:

5.1.2拓宽原始转换

doubleValue public double doubleValue()

在扩展基元转换后,返回

AtomicLong的当前值,作为

double ,具有

VarHandle.getVolatile(java.lang.Object...)指定的记忆效应。

Specified by:

doubleValue类

Number

结果

转换为类型

double后此对象表示的数值。

See The Java™ Language Specification:

5.1.2拓宽原始转换

getPlain public final long getPlain()

返回当前值,读取的内存语义就像变量声明为非

volatile 。

结果

价值

从以下版本开始:

9

setPlain public final void setPlain​(long newValue)

将值设置为

newValue ,设置的内存语义就像变量被声明为非

volatile和非

final 。

参数

newValue - 新值

从以下版本开始:

9

getOpaque public final long getOpaque()

返回当前值,具有

VarHandle.getOpaque(java.lang.Object...)指定的内存效果。

结果

价值

从以下版本开始:

9

setOpaque public final void setOpaque​(long newValue)

将值设置为

newValue ,具有

VarHandle.setOpaque(java.lang.Object...)指定的记忆效果。

参数

newValue - 新值

从以下版本开始:

9

getAcquire public final long getAcquire()

返回当前值,具有

VarHandle.getAcquire(java.lang.Object...)指定的内存效果。

结果

价值

从以下版本开始:

9

setRelease public final void setRelease​(long newValue)

将值设置为

newValue ,具有

VarHandle.setRelease(java.lang.Object...)指定的记忆效果。

参数

newValue - 新值

从以下版本开始:

9

compareAndExchange public final long compareAndExchange​(long expectedValue,

long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchange(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

见证值,如果成功则与预期值相同

从以下版本开始:

9

compareAndExchangeAcquire public final long compareAndExchangeAcquire​(long expectedValue,

long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchangeAcquire(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

见证值,如果成功则与预期值相同

从以下版本开始:

9

compareAndExchangeRelease public final long compareAndExchangeRelease​(long expectedValue,

long newValue)

原子将值设置为

newValue如果当前值,被称为

证人值 ,

== expectedValue如通过指定,记忆效应

VarHandle.compareAndExchangeRelease(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

见证值,如果成功则与预期值相同

从以下版本开始:

9

weakCompareAndSetVolatile public final boolean weakCompareAndSetVolatile​(long expectedValue,

long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSet(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功

从以下版本开始:

9

weakCompareAndSetAcquire public final boolean weakCompareAndSetAcquire​(long expectedValue,

long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetAcquire(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功

从以下版本开始:

9

weakCompareAndSetRelease public final boolean weakCompareAndSetRelease​(long expectedValue,

long newValue)

可能原子将值设置为

newValue如果当前值

== expectedValue如通过指定,记忆效应

VarHandle.weakCompareAndSetRelease(java.lang.Object...) 。

参数

expectedValue - 预期值

newValue - 新值

结果

true如果成功

从以下版本开始:

9

跳过导航

概述

模块

软件包

使用

已过时的

索引

帮助

Java SE 11 & JDK 11

所有类

JavaScript is disabled on your browser.

概要: 

嵌套 | 

字段 | 

构造方法 | 

方法

详细信息: 

字段 | 

构造方法 | 

方法

Report a bug or suggest an enhancement For further API reference and developer documentation see the Java SE Documentation, which contains more detailed, developer-targeted descriptions with conceptual overviews, definitions of terms, workarounds, and working code examples. Java is a trademark or registered trademark of Oracle and/or its affiliates in the US and other countries. Copyright © 1993, 2018, Oracle and/or its affiliates, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.All rights reserved. Use is subject to license terms and the documentation redistribution policy.

突击并发编程JUC系列-原子更新AtomicLong - 知乎

突击并发编程JUC系列-原子更新AtomicLong - 知乎切换模式写文章登录/注册突击并发编程JUC系列-原子更新AtomicLong山间木匠-公众号山间木匠作者 突击并发编程JUC系列演示代码地址: https://github.com/mtcarpenter/JavaTutorial Java 从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。原子类通过 CAS (compare and swap) 、 volatile和native方法实现,比 synchronized 开销更小,执行效率更高,在多线程环境下,无锁的进行原子操作。 Atomic包分类对其进行分类如下: 为了避免一个章节内容过多,导致大家提前下车,会通过几个章节进行 Atomic 包下面的知识讲解。 基本类型基本类型有AtomicBoolean 、 AtomicInteger 、AtomicLong、这 3 个类提供的方法几乎一模一样,本章节以 AtomicLong为案例进行讲解,提前小剧透为了在后面和LongAdder 进行对比,LongAdder 和 AtomicLong 在面试中也被问到过呢。 AtomicLong 的常用方法如下 温馨提示:i++、++i、i--、--i只是为了帮助大家理解、理解、理解,重要的事情说三遍,并不是底层的实现就是它们哟。 小试牛刀古人云“是骡子是马拉出来溜溜“,一段代码撸起来,走你。public class AtomicExample1 {

/**

* 初始化为 0

*/

private static AtomicLong count = new AtomicLong(0);

private static LongUnaryOperator longUnaryOperator = new LongUnaryOperator() {

@Override

public long applyAsLong(long operand) {

return 1;

}

};

private static LongBinaryOperator longBinaryOperator = new LongBinaryOperator() {

@Override

public long applyAsLong(long left, long right) {

return left + right;

}

};

public static void main(String[] args) {

// 以原子方式将当前值加1,返回旧值 (i++): 0

System.out.println("getAndIncrement=" + count.getAndIncrement());

// 以原子方式将当前值加1,返回新值(++i) 两次增加 : 2

System.out.println("incrementAndGet=" + count.incrementAndGet());

//以原子方式将当前值减少 1,返回旧值 (i--):2

System.out.println("incrementAndGet=" + count.getAndDecrement());

//以原子方式将当前值减少 1,返回旧值 (--i):0

System.out.println("incrementAndGet=" + count.decrementAndGet());

// 以原子方式将输入的数值与实例中的值(AtomicLong里的value)相加,并返回结果

System.out.println("addAndGet=" + count.addAndGet(10));

// 以原子方式设置为`newValue`的值,并返回旧值

System.out.println("getAndSet=" + count.getAndSet(100));

// 获取 atomicLong 的 value

System.out.println("get=" + count.get());

System.out.println("*********** JDK 1.8 ***********");

// 使用将给定函数定函数的结果原子更新当前值,返回上一个值

// count.get() 为 1:返回 1

System.out.println("getAndUpdate=" + count.getAndUpdate(longUnaryOperator));

// 返回 applyAsLong 得值

System.out.println("getAndUpdate=" + count.getAndUpdate(longUnaryOperator));

// 获取 atomicLong 的 value

System.out.println("get=" + count.get());

// 使用给定函数应用给当前值和给定值的结果原子更新当前值,返回上一个值

// 返回结果 1,上次结果

System.out.println("getAndAccumulate=" + count.getAndAccumulate(2, longBinaryOperator));

// 返回结果 3 ,上次结果 1 + 2

System.out.println("getAndAccumulate=" + count.getAndAccumulate(2, longBinaryOperator));

// 获取 atomicLong 的 value

System.out.println("get=" + count.get());

}

}

一串代码送给你,运行结果请参考:getAndIncrement=0

incrementAndGet=2

incrementAndGet=2

incrementAndGet=0

addAndGet=10

getAndSet=10

get=100

*********** JDK 1.8 ***********

getAndUpdate=100

getAndUpdate=1

get=1

getAndAccumulate=1

getAndAccumulate=3

get=5

不安全并发计数public class AtomicExample2 {

// 请求总数

public static int requestTotal = 1000;

public static int count = 0;

public static void main(String[] args) throws InterruptedException {

final CountDownLatch countDownLatch = new CountDownLatch(requestTotal);

long start = System.currentTimeMillis();

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

new Thread(() -> {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

add();

countDownLatch.countDown();

}).start();

}

countDownLatch.await();

System.out.println("count=" + count);

System.out.println("耗时:" + (System.currentTimeMillis() - start));

}

private static void add() {

++count;

}

}

懵懂少年是否对 CountDownLatch 有疑问吗?CountDownLatch 又称 倒计数器 , 也就是让一个线程或者多个线程等待其他线程结束后再继续自己的操作,类似加强版 join() 。countDown : 执行一次, 计数器的数值 -1。await :等待计算器的值为 0,才进行后面的操作,就像一个栅栏一样。 AtomicLong 实现并发计数public class AtomicExample3 {

// 请求总数

public static int requestTotal = 5000;

public static AtomicLong count = new AtomicLong(0);

public static void main(String[] args) throws InterruptedException {

final CountDownLatch countDownLatch = new CountDownLatch(requestTotal);

long start = System.currentTimeMillis();

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

new Thread(() -> {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

add();

countDownLatch.countDown();

}).start();

}

countDownLatch.await();

System.out.println("count=" + count.get());

System.out.println("耗时:" + (System.currentTimeMillis() - start));

count.addAndGet(200);

System.out.println("count=" + count.get());

}

private static void add() {

//count.incrementAndGet();

count.getAndIncrement();

}

}

走进源码一段段小小的案例演示,已经无法满足懵懂少年了,那就加餐,加餐,下面分类介绍下面 JDk 1.7 和 JDK1.8 的底层实现。 在 Jdk1.7 中,AtomicLong 的关键代码如下: static {

try {

// 获取内存 value 内存中的地址

valueOffset = unsafe.objectFieldOffset

(AtomicInteger.class.getDeclaredField("value"));

} catch (Exception ex) { throw new Error(ex); }

}

// 省略其他代码.....

public final long getAndIncrement() {

for(;;)

long current = get();

long next = current + 1;

if (compareAndSet(current, next))

return current;

}

}

public final boolean compareAndSet(long expect, long update) {

return unsafe.compareAndSwapLong(this, valueOffset, expect, update);

}

getAndIncrement()进去乍一看,无限循环,这不就如一个痴情男孩一样,一直等待他的女神回信,不回信一直等啊等。long current = get(); 获取 AtomicLong中的 value 值。long next = current + 1;: 在当前记录 + 1。compareAndSet(current, next): 通过 compareAndSet方法来进行原子更新操作,将当前的值跟内存中的值进行比较,相等,则内存中没有被修改,直接写入新的值到主内存中,并return true,否则直接return false。在 Jdk1.8 中,AtomicLong 的关键代码如下:/**

* 原子更新导致值

*

* @return 返回旧值

*/

public final long getAndIncrement() {

return unsafe.getAndAddLong(this, valueOffset, 1L);

}

//

public final long getAndAddLong(Object var1, long var2, long var4) {

long var6;

do {

var6 = this.getLongVolatile(var1, var2);

} while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

return var6;

}

var1: 需要修改的类对象var2:修改的字段的内存地址var6 是修改前字段的值,若是没其余线程修改即与 var2 相等var6+var4: 修改后字段的值,也就是新值compareAndSwapLong :当字段实际值和var6值相当的时候,才会设置其为 var6+var4 。this.getLongVolatile(var1, var2):获取对象obj中偏移量为offset的变量对应 volatile 语义的值。从上面的代码可以看出AtomicLong在 jdk 7 的循环逻辑,在 JDK 8 中原子操作类 unsafe 内置了。之所以内置应该是考虑到这个函数在其他地方也会用到,而内置可以提高复用性。欢迎关注公众号 山间木匠 , 我是小春哥,从事 Java 后端开发,会一点前端、通过持续输出系列技术文章与文会友,如果本文能为您提供帮助,欢迎大家关注、 点赞、分享支持,我们下期再见!发布于 2020-09-22 09:51线程安全Java编程​赞同 1​​添加评论​分享​喜欢​收藏​申请

高并发编程之AtomicLong讲解-CSDN博客

>

高并发编程之AtomicLong讲解-CSDN博客

高并发编程之AtomicLong讲解

最新推荐文章于 2023-07-22 19:15:29 发布

住手丶让我来

最新推荐文章于 2023-07-22 19:15:29 发布

阅读量2.7w

收藏

77

点赞数

14

分类专栏:

并发

文章标签:

AtomicLong

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/weixin_42146366/article/details/87820373

版权

并发

专栏收录该内容

50 篇文章

11 订阅

订阅专栏

一、AtomicLong介绍 AtomicLong是作用是对长整形进行原子操作。 在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。

二、AtomicLong的几个常用方法 ①.创建具有初始值 0 的新 AtomicLong。

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//1、创建具有初始值 0 的新 AtomicLong。

AtomicLong atomicLong = new AtomicLong();

System.out.println("Value:" + atomicLong.get());

}

}

②.创建具有给定初始值的新 AtomicLong。

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//2、创建具有给定初始值的新 AtomicLong。

AtomicLong atomicLong1 = new AtomicLong(10);

System.out.println("Value:" + atomicLong1.get());

}

}

③.addAndGet()方法:以原子方式将给定值添加到当前值,先加上特定的值,再获取结果

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//3、以原子方式将给定值添加到当前值,先加上特定的值,再获取结果

AtomicLong atomicLong2 = new AtomicLong(3);

atomicLong2.addAndGet(5);

System.out.println("Value:" + atomicLong2.get());

}

}

④.getAndAdd()方法:先获取当前值再加上特定的值

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//4、先获取当前值再加上特定的值

AtomicLong atomicLong5 = new AtomicLong(10);

atomicLong5.getAndAdd(5);

System.out.println("Value:" + atomicLong5.get());

}

}

⑤.compareAndSet()方法:如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//5、如果当前值 == 预期值,则以原子方式将该值设置为给定的更新值。

AtomicLong atomicLong3 = new AtomicLong(10);

atomicLong3.compareAndSet(10,15);

System.out.println("Value:" + atomicLong3.get());

}

}

⑥.decrementAndGet()方法:以原子方式将当前值减 1,先减去1再获取值

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//6、 以原子方式将当前值减 1,先减去1再获取值

AtomicLong atomicLong4 = new AtomicLong(10);

atomicLong4.decrementAndGet();

System.out.println("Value:" + atomicLong4.get());

}

}

⑦.getAndDecrement()方法:先获取当前值再减1

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//7、先获取当前值再减1

AtomicLong atomicLong6 = new AtomicLong();

atomicLong6.getAndDecrement();

System.out.println("Value:" + atomicLong6.get());

}

}

⑧.getAndIncrement()方法:先获取当前值再加1

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//8、先获取当前值再加1

AtomicLong atomicLong7 = new AtomicLong();

atomicLong7.getAndIncrement();

System.out.println("Value:" + atomicLong7.get());

}

}

⑨.incrementAndGet()方法:先加1再获取当前值

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//9、先加1再获取当前值

AtomicLong atomicLong9 = new AtomicLong();

atomicLong9.incrementAndGet();

System.out.println("Value:" + atomicLong9.get());

}

}

⑩.getAndSet()方法:先获取当前值再设置新的值

package chapter3.AtomicLongTest;

import java.util.concurrent.atomic.AtomicLong;

/**

* @author czd

*/

public class AtomicLongTest {

public static void main(String[] args) {

//10、先获取当前值再设置新的值

AtomicLong atomicLong8 = new AtomicLong();

atomicLong8.getAndSet(20);

System.out.println("Value:" + atomicLong8.get());

}

}

优惠劵

住手丶让我来

关注

关注

14

点赞

77

收藏

觉得还不错?

一键收藏

知道了

5

评论

高并发编程之AtomicLong讲解

一、AtomicLong介绍AtomicLong是作用是对长整形进行原子操作。在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。二、AtomicLong的几个常用方法①.创建具有初始值 0 的新 AtomicLong。package chapter3.Atom...

复制链接

扫一扫

专栏目录

汪文君高并发编程实战视频资源下载.txt

08-08

├─第一阶段

│      源码+ppt.rar

│      高并发编程第一阶段01讲、课程大纲及主要内容介绍.wmv

│      高并发编程第一阶段02讲、简单介绍什么是线程.wmv

│      高并发编程第一阶段03讲、创建并启动线程.mp4

│      高并发编程第一阶段04讲、线程生命周期以及start方法源码剖析.mp4

│      高并发编程第一阶段05讲、采用多线程方式模拟银行排队叫号.mp4

│      高并发编程第一阶段06讲、用Runnable接口将线程的逻辑执行单元从控制中抽取出来.mp4

│      高并发编程第一阶段07讲、策略模式在Thread和Runnable中的应用分析.mp4

│      高并发编程第一阶段08讲、构造Thread对象你也许不知道的几件事.mp4

│      高并发编程第一阶段09讲、多线程与JVM内存结构的关系,虚拟机栈实验.mp4

│      高并发编程第一阶段10讲、Thread构造函数StackSize详细讲解.mp4

│      高并发编程第一阶段11讲、Thread构造函数StackSize详细讲解-续.mp4

│      高并发编程第一阶段12讲、Daemon线程的创建以及使用场景分析.mp4

│      高并发编程第一阶段13讲、线程ID,优先级讲解.mp4

│      高并发编程第一阶段14讲、Thread的join方法详细介绍,结合一个典型案例.mp4

│      高并发编程第一阶段15讲、Thread中断Interrupt方法详细讲解.mp4

│      高并发编程第一阶段16讲、采用优雅的方式结束线程生命周期.mp4

│      高并发编程第一阶段17讲、Thread API综合实战,编写ThreadService实现暴力结束线程的综合实战.mp4

│      高并发编程第一阶段18讲、数据同步的引入与Synchronized的简单介绍.mp4

│      高并发编程第一阶段19讲、结合jconsole,jstack以及汇编指令认识synchronized关键字.mp4

│      高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4

│      高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4

│      高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4

│      高并发编程第一阶段23讲、多线程死锁分析,案例介绍.mp4

│      高并发编程第一阶段24讲、线程间通信快速入门,使用wait和notify进行线程间的数据通信.mp4

│      高并发编程第一阶段25讲、多Produce多Consume之间的通讯导致出现程序假死的原因分析.mp4

│      高并发编程第一阶段26讲、多线程下的生产者消费者模型,以及详细介绍notifyAll方法.mp4

│      高并发编程第一阶段27讲、wait和sleep的本质区别是什么,深入分析(面试常见问题).mp4

│      高并发编程第一阶段28讲、线程生产者消费者的综合实战结合Java8语法.mp4

│      高并发编程第一阶段29讲、如何实现一个自己的显式锁Lock精讲上.mp4

│      高并发编程第一阶段30讲、如何实现一个自己的显式锁Lock精讲下(让锁具备超时功能).mp4

│      高并发编程第一阶段31讲、如何给你的应用程序注入钩子程序,Linux下演示.mp4

│      高并发编程第一阶段32讲、如何捕获线程运行期间的异常.mp4

│      高并发编程第一阶段33讲、ThreadGroup API介绍之一.mp4

│      高并发编程第一阶段34讲、ThreadGroup API介绍之二.mp4

│      高并发编程第一阶段35讲、线程池原理与自定义线程池.mp4

│      高并发编程第一阶段36讲、自定义个简单的线程池并且测试.mp4

│      高并发编程第一阶段37讲、给线程池增加拒绝策略以及停止方法.mp4

│      高并发编程第一阶段38讲、给线程池增加自动扩充线程数量,以及闲时自动回收的功能.mp4

│      高并发编程第一阶段39讲、课程结束,内容回顾,下季内容预告.mp4

├─第二阶段

│       Java并发编程.png

│       ppt+源码.rar

│       高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv

│       高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv

│       高并发编程第二阶段03讲、介绍三种高效优雅的Singleto

JAVA AtomicLong 实现循环自增流水号

最新发布

athjyh的博客

12-25

471

java Atomiclong 实现循环自增流水号

5 条评论

您还未登录,请先

登录

后发表或查看评论

Java concurrency之AtomicLong原子类_动力节点Java学院整理

08-30

AtomicLong是作用是对长整形进行原子操作。下面通过本文给大家介绍Java concurrency之AtomicLong原子类的相关知识,感兴趣的朋友一起看看吧

AtomicLong 原子操作

SongYuxinIT的博客

08-30

505

AtomicLong是作用是对长整形进行原子操作。

在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。

创建具有初始值 0 的新 AtomicLong

private AtomicLong sendCount = new AtomicLong(0);

创建具有给定初始值10的新 AtomicLong

private AtomicLong sendCount10 = .

原子类型AtomicLong用法探究

乐学吧

07-22

326

LongAdder 是把 value 分成若干cell,并发量低的时候,直接 CAS 更新值,成功即结束。并发量高的情况,CAS更新某个cell值和需要时对cell数据扩容,成功结束;​​ 是 Java 提供的一个原子长整型类,提供了对长整型数据的原子性操作。​ 对象的原子性操作,确保在多线程环境下的数据安全性。​ 的原子性操作,我们可以在多线程环境下安全地递增 ​。​​ 的使用方法和功能与标准 Java 中的 ​。​ 可以确保对长整型数据的操作是线程安全的。​,避免了竞态条件的问题。

java 原子long_Java原子类--AtomicLong

weixin_39630182的博客

02-13

2046

AtomicLong介绍和函数列表AtomicLong是作用是对长整形进行原子操作。在32位操作系统中,64位的long 和 double 变量由于会被JVM当作两个分离的32位来进行操作,所以不具有原子性。而使用AtomicLong能让long的操作保持原子型。AtomicLong函数列表// 构造函数AtomicLong()// 创建值为initialValue的AtomicLong对象Ato...

Java原子类:AtomicLong、LongAdder、LongAccumulator详解

li_w_ch的博客

01-12

1123

JUC包提供了一系列的原子性操作类,这些类都是使用非阻塞算法CAS实现的,相比使用锁实现原子性操作,这在性能上有很大的提高。

1、AtomicLong

JUC并发包中包含有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们的原理类似。AtomicLong是原子性递增或者递减类,其内部使用Unsafe来实现。

多线程使用AtomicLong统计0的个数:

// 统计0的个数

public class Atomic {

// 创建Long型原子计数

并发编程 — 原子类 AtomicLong 详解

small_love的专栏

12-12

948

与AtomicInteger非常类似,AtomicLong提供了原子性操作long类型数据的解决方案,AtomicLong所提供的原子性方法在使用习惯上也与AtomicInteger非常一致。我们不再详细解释每一个方法如何使用,可以参考 《AtomicInteger》 。AtomicInteger类中最为关键的方法为compareAndSwapInt,同样,在AtomicLong类中也提供了类似的方法compareAndSwapLong,但是该方法要比compareAndSwapInt复杂很多。

我们知道

原子类型:AtomicLong详解

wyaoyao93的博客

04-19

2667

与AtomicInteger非常类似,AtomicLong提供了原子性操作long类型数据的解决方案,AtomicLong同样也继承自Number类,AtomicLong所提供的原子性方法在使用习惯上也与AtomicInteger非常一致。

这里就不多介绍

1 compareAndSwapLong和compareAndSwapInt

AtomicInteger类中最为关键的方法为compareAndSwapInt,同样,在AtomicLong类中也提供了类似的方法compareAndSwapLong,但是该

简单对比AtomicLong和LongAdder

心向阳光的天域的博客

02-15

811

简单对比AtomicLong和LongAdder

汪文君高并发编程实战视频资源全集

08-08

 高并发编程第三阶段06讲 AtomicLong源码分析.mp4  高并发编程第三阶段07讲 AtomicReference详解,CAS算法带来的ABA问题详解.mp4  高并发编程第三阶段08讲 AtomicStampReference详解,解决CAS带来的ABA问题.mp4 ...

java编发编程:JUC综合讲解

08-09

Java 并发编程在现代软件开发中占据重要地位,尤其是在多核处理器的时代。JUC(java.util.concurrent)库是 Java 标准库的一部分,提供了丰富的多线程并发工具,旨在帮助开发者编写高性能、高可伸缩性的并发程序。...

AtomicLong

lzc_23的博客

05-10

650

本文翻译自http://tutorials.jenkov.com/java-util-concurrent/atomiclong.html,人工翻译,仅供学习交流。

AtomicLong

AtomicLong类为您提供了一个Long变量,它可以原子地读写。它也包含像compareAndSet()这样的高级原子操作。AtomicLong类位于java.util.concurrent.atomic包中,因此完整的类名java.util.concurrent.atomic.AtomicLong。本文描述了在Jav

并发安全的计数统计类:AtomicLong和LongAdder

08-03

613

文章目录AtomicLong概述AtomicLong实现原理AtomicLong的缺陷LongAdderLongAdder实现原理LongAdder源码分析AtomicLong和 LongAdder对比代码测试

AtomicLong

概述

我们在进行计数统计的时,通常会使用AtomicLong来实现,AtomicLong能保证并发情况下计数的准确性,其内部通过CAS来解决并发安全性的问题。

AtomicLong实现原理

说到线程安全的计数统计工具类,肯定少不了Atomic下的几个原子类。AtomicLong

突击并发编程JUC系列-原子更新AtomicLong

havendream的博客

09-22

199

突击并发编程JUC系列演示代码地址:

https://github.com/mtcarpenter/JavaTutorial

Java 从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。原子类通过 CAS (compare and swap) 、 volatile和native方法实现,比 synchronized 开销更小,执行效率更高,在多线程环境下,无锁的进行.

java多线程之AtomicLong原子类(JDK8)

夏夜凉月

05-03

1047

引言

有的同学可能会问这个问题,有了Long类型,为什么还要弄一个AtomicLong类出来?

因为在32位的操作系统中,64位的Long类型变量会被jvm拆分为两个32位的来操作,因此不具备原子性。而AtomicLong类型可以保证原子性。

1、AtomicLong介绍

AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似。本章以J...

AtomicLong和LongAdder的区别

weixin_30756499的博客

11-29

45

AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的。

LongAdder在AtomicLong的基础上将单点的更新压力分散到各个节点,在低并发的时候通过对base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并发的时候通过分散提高了性能。 缺点是LongAdder在统计的...

4.原子操作类:AtomicLong、LongAdderLong、Accumulator

页页的博客

06-30

317

JUC包中有AtomicInteger、AtomicLong和AtomicBoolean等原子性操作类,它们原理类似,下面以AtomicLong为例进行讲解。

递增和递减操作代码

上述代码中,valueOffset为AtomicLong在static语句块中进行初始化时通过。可以看到,上述四个方法都是(原子性操作)实现的。

AtomicLong使用示例

AtomicLong使用CAS非阻塞算法,性能比使用synchronized等的阻塞算法实现同步好很多。但在高并发下,大量线程会同时去竞争更新同一个原

juc高并发编程面试

09-28

JUC(Java Util Concurrent)是Java中用于多线程开发的类库,它包含了许多实用工具和类,用于解决高并发编程中的各种问题。使用JUC可以提高多线程程序的性能和可伸缩性,并且简化了编程过程。

JUC的主要优点有:

1. 提供了一些高效的并发容器,如ConcurrentHashMap、ConcurrentLinkedQueue等,这些容器可以在高并发环境下提供线程安全的访问和操作。

2. 提供了一些高级的同步工具,如CountDownLatch、CyclicBarrier等,这些工具可以协调多个线程之间的操作,实现复杂的并发控制逻辑。

3. 提供了一些并发执行的辅助类,如Future、ExecutorService等,可以方便地实现异步任务的执行和结果的获取。

4. 提供了一些原子操作类,如AtomicInteger、AtomicLong等,可以在没有锁的情况下进行线程安全的操作。

在面试中,JUC是一个非常重要的话题。面试官可能会提问JUC的

“相关推荐”对你有帮助么?

非常没帮助

没帮助

一般

有帮助

非常有帮助

提交

住手丶让我来

CSDN认证博客专家

CSDN认证企业博客

码龄6年

暂无认证

236

原创

17万+

周排名

5万+

总排名

54万+

访问

等级

6416

积分

182

粉丝

693

获赞

69

评论

1542

收藏

私信

关注

热门文章

高并发编程之AtomicReference讲解

51873

网络安全知识竞赛选择题(1-30题)

31059

高并发编程之CopyOnWriteArrayList介绍

29912

网络安全知识竞赛选择题(31-60题)

29481

高并发编程之AtomicLong讲解

27720

分类专栏

Java基础

16篇

大数据

2篇

计算机网络

操作系统

Nginx

2篇

Dubbo

4篇

Docker

2篇

Zookeeper

6篇

ELK

2篇

MySQL

20篇

Redis

13篇

消息队列

2篇

加密

3篇

并发

50篇

Linux系统

29篇

数据结构

2篇

其他

10篇

Spring Boot框架

14篇

信息安全

15篇

设计模式

9篇

Python

5篇

ThinkPHP

4篇

Bootstrap

7篇

Tomcat

17篇

最新评论

IDEA下运行Web项目 页面出现中文乱码

A_n_n_:

错误: 找不到或无法加载主类 Dfile.encoding=UTF-8

什么是代理模式?

weixin_43947205:

这和你写的装饰者模式有啥区别?

高并发编程之AtomicReferenceArray讲解

kingtopest:

这是从哪里抄来的东西,自己看明白了吗?!复制粘贴的都这么不利索,好意思吗!

Volatile原理解析

lucky J:

重新读取不意味需要重新执行i++,因为之前已经执行了读取i、temp = i + 1操作,所以计算操作已经执行完毕了,直接进行assign,然后store->write 刷回主内存

Volatile原理解析

wzc10101:

为什么线程B重新读取i之后,跳过了temp = i + 1,直接执行了i = temp,不太理解

您愿意向朋友推荐“博客详情页”吗?

强烈不推荐

不推荐

一般般

推荐

强烈推荐

提交

最新文章

日常工作用到的相关命令【持续更新】

从Hadoop框架讨论大数据生态

大数据概论

2023年1篇

2021年2篇

2020年72篇

2019年162篇

2018年1篇

目录

目录

分类专栏

Java基础

16篇

大数据

2篇

计算机网络

操作系统

Nginx

2篇

Dubbo

4篇

Docker

2篇

Zookeeper

6篇

ELK

2篇

MySQL

20篇

Redis

13篇

消息队列

2篇

加密

3篇

并发

50篇

Linux系统

29篇

数据结构

2篇

其他

10篇

Spring Boot框架

14篇

信息安全

15篇

设计模式

9篇

Python

5篇

ThinkPHP

4篇

Bootstrap

7篇

Tomcat

17篇

目录

评论 5

被折叠的  条评论

为什么被折叠?

到【灌水乐园】发言

查看更多评论

添加红包

祝福语

请填写红包祝福语或标题

红包数量

红包个数最小为10个

红包总金额

红包金额最低5元

余额支付

当前余额3.43元

前往充值 >

需支付:10.00元

取消

确定

下一步

知道了

成就一亿技术人!

领取后你会自动成为博主和红包主的粉丝

规则

hope_wisdom 发出的红包

实付元

使用余额支付

点击重新获取

扫码支付

钱包余额

0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

这一次,彻底搞懂Java并发包中的Atomic原子类 - 知乎

这一次,彻底搞懂Java并发包中的Atomic原子类 - 知乎切换模式写文章登录/注册这一次,彻底搞懂Java并发包中的Atomic原子类向si瑶雅思上岸!一、初始Atomic并发包从JDK1.5开始,Java在java.util.concurrent.atomic包下引入了一些Atomic相关的原子操作类,这些类避免使用加锁来实现同步,从而更加方便、高效的实现原子操作。atomic包下的所有类如下图所示:Atomic包下所有的原子类都只适用于单个元素,即只能保证一个基本数据类型、对象、或者数组的原子性。根据使用范围,可以将这些类分为四种类型,分别为原子 更新基本类型 、 原子更新数组 、 原子更新引用 、 原子更新属性 。1.原子更新基本类型atomic包下原子更新基本数据类型包括AtomicInteger、AtomicLong、AtomicBoolean三个类,分别提供了原子更新整数类型、原子更新长整数类型和原子更新布尔类型的功能。这里,我们以AtomicInteger为例来学习如何使用。AtomicInteger中提供了很多方法供我们调用,如:// 获取当前值,然后自加,相当于i++

getAndIncrement()

// 获取当前值,然后自减,相当于i--

getAndDecrement()

// 自加1后并返回,相当于++i

incrementAndGet()

// 自减1后并返回,相当于--i

decrementAndGet()

// 获取当前值,并加上预期值

getAndAdd(int delta)

// 获取当前值,并设置新值

int getAndSet(int newValue)

// ...需要注意的是这些方法都是原子操作,在多线程下也能够保证原子性以incrementAndGet方法为例:AtomicInteger atomicInteger = new AtomicInteger();

private int index;

public void increase() throws InterruptedException {

new Thread(() -> {

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

index = atomicInteger.incrementAndGet();

}

}).start();

new Thread(() -> {

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

index = atomicInteger.incrementAndGet();

}

}).start();

Thread.sleep(1000);

System.out.println("-----" + index); // 输出结果20000

}在increase方法中开启了两个线程并使用AtomicInteger对index进行自增操作,每次的输出结果都为20000.2.原子更新引用类型基本类型的原子类只能更新一个变量,如果需要原子更新多个变量,则需要使用引用类型原子类。引用类型的原子类包括AtomicReference、AtomicStampedReference、AtomicMarkableReference三个。AtomicReference 引用原子类AtomicStampedReference 原子更新带有版本号的引用类型。该类将整数值与引用关联起来,可用于解决原子的更新数据和数据的版本号,可以解决使用 CAS 进行原子更新时可能出现的 ABA 问题。(关于CAS及ABA问题后文详细分析)AtomicMarkableReference 原子更新带有标记的引用类型。该类将 boolean 标记与引用关联起来。接下来以AtomicReference为例来分析,首先看下AtomicReference的类结构:public class AtomicReference implements java.io.Serializable {

public final V get() {

return value;

}

public final void set(V newValue) {

value = newValue;

}

public final boolean compareAndSet(V expectedValue, V newValue) {

return VALUE.compareAndSet(this, expectedValue, newValue);

}

// ...省略其他

}可以看到AtomicReference是一个泛型类,内部设置及更新引用类型数据的方法。以compareAndSet方法为例来看如何使用。public class Book {

public String name;

public int price;

public Book(String name, int price) {

this.name = name;

this.price = price;

}

}

AtomicReference atomicReference = new AtomicReference<>();

Book book1 = new Book("三国演义", 42);

atomicReference.set(book1);

Book book2 = new Book("水浒传", 40);

atomicReference.compareAndSet(book1, book2);

System.out.println("Book name is " + atomicReference.get().name + ",价格是" + atomicReference.get().price);输出结果为:Book name is 水浒传,价格是40上述代码首先将book1关联AtomicReference,接着又实例化了book2。调用compareAndSet方法传入book1和book2两个参数,通过CAS更新book。首先判断期望的是不是book1,如果是则更新为book2.否则继续自旋知道更新成功。3.原子更新数组这里原子更新数组并不是对数组本身的原子操作,而是对数组中的元素。主要包括3个类:AtomicIntegerArray、AtomicLongArray及AtomicReferenceArray,分别表示原子更新整数数组的元素、原子更新长整数数组的元素以及原子更新引用类型数组的元素。我们以AtomicIntegerArray为例来看:public class AtomicIntegerArray implements java.io.Serializable {

// final类型的int数组

private final int[] array;

// 获取数组中第i个元素

public final int get(int i) {

return (int)AA.getVolatile(array, i);

}

// 设置数组中第i个元素

public final void set(int i, int newValue) {

AA.setVolatile(array, i, newValue);

}

// CAS更改第i个元素

public final boolean compareAndSet(int i, int expectedValue, int newValue) {

return AA.compareAndSet(array, i, expectedValue, newValue);

}

// 获取第i个元素,并加1

public final int getAndIncrement(int i) {

return (int)AA.getAndAdd(array, i, 1);

}

// 获取第i个元素并减1

public final int getAndDecrement(int i) {

return (int)AA.getAndAdd(array, i, -1);

}

// 对数组第i个元素加1后再获取

public final int incrementAndGet(int i) {

return (int)AA.getAndAdd(array, i, 1) + 1;

}

// 对数组第i个元素减1后再获取

public final int decrementAndGet(int i) {

return (int)AA.getAndAdd(array, i, -1) - 1;

}

// ... 省略

}可以看到,在AtomicIntegerArray内部维护了一个final修饰的int数组,且类中所有的操作都是针对数组元素的操作。同时,这些方法都是原子操作,可以保证多线程下数据的安全性。4.原子更新对象属性如果直选哟更新某个对象中的某个字段,可以使用更新对象字段的原子类。包括三个类,AtomicIntegerFieldUpdater、AtomicLongFieldUpdater以及AtomicReferenceFieldUpdater。需要注意的是这些类的使用需要满足以下条件才可。被操作的字段不能是static类型;被操纵的字段不能是final类型;被操作的字段必须是volatile修饰的;属性必须对于当前的Updater所在区域是可见的。下面以AtomicIntegerFieldUpdater为例,结合前例中的Book类来更新Book的价格,注意将price用volatile修饰。public class Book {

public String name;

public volatile int price;

public Book(String name, int price) {

this.name = name;

this.price = price;

}

}

AtomicIntegerFieldUpdater updater = AtomicIntegerFieldUpdater.newUpdater(Book.class, "price");

Book book = new Book("三国演义", 42);

updater.set(book, 50);

System.out.println( "更新后的价格是" + updater.get(book));输出结果如下:更新后的价格是50实例化一个Book,价格为42,通过AtomicIntegerFieldUpdater可以将价格修改为50。二、CAS前文中已经提到Atomic包下的类是无锁操作,无锁的实现就得益于CAS。在前几篇文章中CAS的概念都有提及。那么这里我们就来详细的认识一下什么是CAS。CAS是Compare And Swap的简称,即比较并交换的意思。CAS是一种无锁算法,其算法思想如下:CAS的函数公式:compareAndSwap(V,E,N); 其中V表示要更新的变量,E表示预期值,N表示期望更新的值。调用compareAndSwap函数来更新变量V,如果V的值等于期望值E,那么将其更新为N,如果V的值不等于期望值E,则说明有其它线程跟新了这个变量,此时不会执行更新操作,而是重新读取该变量的值再次尝试调用compareAndSwap来更新。可见CAS其实存在一个循环的过程,如果有多个线程在同时修改这一个变量V,在修改之前会先拿到这个变量的值,再和变量对比看是否相等,如果相等,则说明没有其它线程修改这个变量,自己更新变量即可。如果发现要修改的变量和期望值不一样,则说明再读取变量V的值后,有其它线程对变量V做了修改,那么,放弃本次更新,重新读变量V的值,并再次尝试修改,直到修改成功为止。这个循环过程一般也称作 自旋 ,CAS操作的整个过程如下图所示:2.CAS存在的缺点虽然通过CAS可以实现无锁同步,但是CAS也有其局限性和问题所在。(1)只能保证一个共享变量的原子性CAS不像synchronized和RetranLock一样可以保证一段代码和多个变量的同步。对于多个共享变量操作是CAS是无法保证的,这时候必须使用枷锁来是实现。(2)存在性能开销问题由于CAS是一个自旋操作,如果长时间的CAS不成功会给CPU带来很大的开销。(3)ABA问题因为CAS是通过检查值有没有发生改变来保证原子性的,假若一个变量V的值为A,线程1和线程2同时都读取到了这个变量的值A,此时线程1将V的值改为了B,然后又改回了A,期间线程2一直没有抢到CPU时间片。知道线程1将V的值改回A后线程2才得到执行。那么此时,线程2并不知道V的值曾经改变过。这个问题就被成为 ABA问题 。ABA问题的解决其实也容易处理,即添加一个版本号,更次更新值同时也更新版本号即可。上文中提到的AtomicStampedReference就是用来解决ABA问题的。3.CPU对CAS的支持在操作系统中CAS是一种系统原语,原语由多条指令组成,且原语的执行是连续不可中断的。因此CAS实际上是一条CPU的原子指令,虽然看上去CAS是一个先比较再交换的操作,但实际上这个过程是由CPU保证了原子操作。4.CAS与Atomic原子类了解了CAS,我们就来看下Atomic包中的原子类是如何使用CAS实现原子操作的。我们以AtomicInteger为例来看.public class AtomicInteger extends Number implements java.io.Serializable {

private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();

}

public final int getAndSet(int newValue) {

return U.getAndSetInt(this, VALUE, newValue);

}

public final int getAndIncrement() {

return U.getAndAddInt(this, VALUE, 1);

}

public final int getAndDecrement() {

return U.getAndAddInt(this, VALUE, -1);

}

public final int getAndAdd(int delta) {

return U.getAndAddInt(this, VALUE, delta);

}

public final int incrementAndGet() {

return U.getAndAddInt(this, VALUE, 1) + 1;

}

public final int decrementAndGet() {

return U.getAndAddInt(this, VALUE, -1) - 1;

}可以看到在AtomicInteger类中,所有的操作都是通过一个类型为Unsafe的成员变量来实现的。Unsafe类是位于sun.misc包下的一个类,这个类中提供了用于执行低级别、不安全的操作方法,其中就包括了CAS的能力。三、CAS的实现类–UnsafeUnsafe是一个神奇且鲜为人知的Java类,因为在平时开发中很少用到它。但是这个类中为我们提供了相当多的功能,它即可以让Java语言像C语言指针一样操作内存,同时还提供了CAS、内存屏障、线程调度、对象操作、数组操作等能力,如下图。下面就来简单的认识一下Unsafe类。1.获取Unsafe实例Unsafe类是一个单例,并且提供了一个getUnsafe的方法来获取Unsafe的实例。但是,这个方法只有在引导类加载器加载Unsafe类是调用才合法,否则会抛出一个SecurityException异常,如下:Exception in thread "main" java.lang.SecurityException: Unsafe

at jdk.unsupported/sun.misc.Unsafe.getUnsafe(Unsafe.java:99)

at atomic.AtomicDemo.increase(AtomicDemo.java:28)

at atomic.AtomicDemo.main(AtomicDemo.java:34)因此,想要获取Unsafe类的实例就需要另辟蹊径了。使用反射来获取Unsafe实例是一个比较好的方案,实现代码如下:try {

Field field = Unsafe.class.getDeclaredField("theUnsafe");

field.setAccessible(true);

Unsafe unsafe = (Unsafe) field.get(null);

} catch (Exception e) {

e.printStackTrace();

}2.Unsafe类中的CASUnsafe类中与CAS相关的主要有以下几个方法// 第一个参数o为给定对象,offset为对象内存的偏移量,通过这个偏移量迅速定位字段并设置或获取该字段的值,expected表示期望值,x表示要设置的值,下面3个方法都通过CAS原子指令执行操作。

public final native boolean compareAndSetInt(Object o,long offset,int expected,int x);

public final native boolean compareAndSetObject(Object o, long offset,Object expected,Object x);

public final native boolean compareAndSetLong(Object o, long offset,long expected,long x);可以看到,这些方法都是native方法,调用的底层代码实现。在JDK1.8中还引入了getAndAddInt、getAndAddLong、getAndSetInt、getAndSetLong、getAndSetObject等方法来支持不同类型CAS操作。而AtomicInteger中也正是使用了这里的方法才实现的CAS操作。3.线程调度相关在Unsafe中提供了线程挂起、恢复及锁机制相关的方法。//取消阻塞线程

public native void unpark(Object thread);

//阻塞线程

public native void park(boolean isAbsolute, long time);

//获得对象锁(可重入锁)

@Deprecated

public native void monitorEnter(Object o);

//释放对象锁

@Deprecated

public native void monitorExit(Object o);

//尝试获取对象锁

@Deprecated

public native boolean tryMonitorEnter(Object o);在上篇文章讲解RetranLock与AQS时涉及到线程挂起的操作其实也是调用的Unsafe的park方法。// LockSupport

private static final Unsafe U = Unsafe.getUnsafe();

public static void park(Object blocker) {

Thread t = Thread.currentThread();

setBlocker(t, blocker);

U.park(false, 0L);

setBlocker(t, null);

}4.### 对象操作Unsafe还提供了对象实例化及操作对象属性相关的方法//返回对象成员属性在内存地址相对于此对象的内存地址的偏移量

public native long objectFieldOffset(Field f);

//获得给定对象的指定地址偏移量的值,与此类似操作还有:getInt,getDouble,getLong,getChar等

public native Object getObject(Object o, long offset);

//给定对象的指定地址偏移量设值,与此类似操作还有:putInt,putDouble,putLong,putChar等

public native void putObject(Object o, long offset, Object x);

//从对象的指定偏移量处获取变量的引用,使用volatile的加载语义

public native Object getObjectVolatile(Object o, long offset);

//存储变量的引用到对象的指定的偏移量处,使用volatile的存储语义

public native void putObjectVolatile(Object o, long offset, Object x);

//有序、延迟版本的putObjectVolatile方法,不保证值的改变被其他线程立即看到。只有在field被volatile修饰符修饰时有效

public native void putOrderedObject(Object o, long offset, Object x);

//绕过构造方法、初始化代码来创建对象

public native Object allocateInstance(Class cls) throws InstantiationException;Unsafe中提供的allocateInstance方法可以绕过对象的构造方法直接创建对象,Gson解析json反序列化对象时就有用到这个方法。// 来自Gson#UnsafeAllocator

public abstract T newInstance(Class var1) throws Exception;

public static UnsafeAllocator create() {

try {

Class unsafeClass = Class.forName("sun.misc.Unsafe");

Field f = unsafeClass.getDeclaredField("theUnsafe");

f.setAccessible(true);

final Object unsafe = f.get((Object)null);

final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);

return new UnsafeAllocator() {

public T newInstance(Class c) throws Exception {

assertInstantiable(c);

return allocateInstance.invoke(unsafe, c);

}

};

} catch (Exception var6) {

// ...省略异常处理

}

}关于Gson使用allocateInstance实例化对象的详细过程可以可以参考 《一个非静态内部类引起的空指针》5.### Unsafe的其它功能除了CAS、线程调度、对象相关的功能外,Unsafe还提供了内存操作,可以实现堆外内存的分配。提供的数组相关的方法来定位数组中每个元素在内存中的位置,等等…由于不是本篇文章的重点,这里就不一一介绍了。感兴趣的可以自行查阅。最后来自小编的福利小编整理了一份大厂真题的面试资料,以及2021最新Java核心技术整理的资料集锦,需要领取的小伙伴可以 私聊关注我 免费领取 ,编程的世界永远向所有热爱编程的人开放,这是一个自由,平等,共享的世界,我始终是这样坚信的。喜欢小编的分享可以点赞关注哦,小编持续为你分享最新文章 和 福利领取哦发布于 2021-07-08 21:59Java多线程Thread(通讯标准)​赞同 8​​添加评论​分享​喜欢​收藏​申请

使用Atomic - 廖雪峰的官方网站

使用Atomic - 廖雪峰的官方网站

Index

廖雪峰的官方网站

Blog

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

More

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

Java教程

手写Spring

手写Tomcat

Makefile教程

Python教程

JavaScript教程

区块链教程

SQL教程

Git教程

文章

问答

 

Profile

Passkey

Sign Out

Sign In

English

简体中文

Index

Java教程

Java快速入门

Java简介

安装JDK

第一个Java程序

Java代码助手

使用IDE

使用IDE练习插件

Java程序基础

Java程序基本结构

变量和数据类型

整数运算

浮点数运算

布尔运算

字符和字符串

数组类型

流程控制

输入和输出

if判断

switch多重选择

while循环

do while循环

for循环

break和continue

数组操作

遍历数组

数组排序

多维数组

命令行参数

面向对象编程

面向对象基础

方法

构造方法

方法重载

继承

多态

抽象类

接口

静态字段和静态方法

作用域

内部类

classpath和jar

class版本

模块

Java核心类

字符串和编码

StringBuilder

StringJoiner

包装类型

JavaBean

枚举类

记录类

BigInteger

BigDecimal

常用工具类

异常处理

Java的异常

捕获异常

抛出异常

自定义异常

NullPointerException

使用断言

使用JDK Logging

使用Commons Logging

使用Log4j

使用SLF4J和Logback

反射

Class类

访问字段

调用方法

调用构造方法

获取继承关系

动态代理

注解

使用注解

定义注解

处理注解

泛型

什么是泛型

使用泛型

编写泛型

擦拭法

extends通配符

super通配符

泛型和反射

集合

Java集合简介

使用List

编写equals方法

使用Map

编写equals和hashCode

使用EnumMap

使用TreeMap

使用Properties

使用Set

使用Queue

使用PriorityQueue

使用Deque

使用Stack

使用Iterator

使用Collections

IO

File对象

InputStream

OutputStream

Filter模式

操作Zip

读取classpath资源

序列化

Reader

Writer

PrintStream和PrintWriter

使用Files

日期与时间

基本概念

Date和Calendar

LocalDateTime

ZonedDateTime

DateTimeFormatter

Instant

最佳实践

单元测试

编写JUnit测试

使用Fixture

异常测试

条件测试

参数化测试

正则表达式

正则表达式简介

匹配规则

复杂匹配规则

分组匹配

非贪婪匹配

搜索和替换

加密与安全

编码算法

哈希算法

BouncyCastle

Hmac算法

对称加密算法

口令加密算法

密钥交换算法

非对称加密算法

签名算法

数字证书

多线程

多线程基础

创建新线程

线程的状态

中断线程

守护线程

线程同步

同步方法

死锁

使用wait和notify

使用ReentrantLock

使用Condition

使用ReadWriteLock

使用StampedLock

使用Semaphore

使用Concurrent集合

使用Atomic

使用线程池

使用Future

使用CompletableFuture

使用ForkJoin

使用ThreadLocal

使用虚拟线程

Maven基础

Maven介绍

依赖管理

构建流程

使用插件

模块管理

使用mvnw

发布Artifact

网络编程

网络编程基础

TCP编程

UDP编程

发送Email

接收Email

HTTP编程

RMI远程调用

XML与JSON

XML简介

使用DOM

使用SAX

使用Jackson

使用JSON

JDBC编程

JDBC简介

JDBC查询

JDBC更新

JDBC事务

JDBC Batch

JDBC连接池

函数式编程

Lambda基础

方法引用

使用Stream

创建Stream

使用map

使用filter

使用reduce

输出集合

其他操作

设计模式

创建型模式

工厂方法

抽象工厂

生成器

原型

单例

结构型模式

适配器

桥接

组合

装饰器

外观

享元

代理

行为型模式

责任链

命令

解释器

迭代器

中介

备忘录

观察者

状态

策略

模板方法

访问者

Web开发

Web基础

Servlet入门

Servlet开发

Servlet进阶

重定向与转发

使用Session和Cookie

JSP开发

MVC开发

MVC高级开发

使用Filter

修改请求

修改响应

使用Listener

部署

Spring开发

IoC容器

IoC原理

装配Bean

使用Annotation配置

定制Bean

使用Resource

注入配置

使用条件装配

使用AOP

装配AOP

使用注解装配AOP

AOP避坑指南

访问数据库

使用JDBC

使用声明式事务

使用DAO

集成Hibernate

集成JPA

集成MyBatis

设计ORM

开发Web应用

使用Spring MVC

使用REST

集成Filter

使用Interceptor

处理CORS

国际化

异步处理

使用WebSocket

集成第三方组件

集成JavaMail

集成JMS

使用Scheduler

集成JMX

Spring Boot开发

第一个Spring Boot应用

使用开发者工具

打包Spring Boot应用

瘦身Spring Boot应用

使用Actuator

使用Profiles

使用Conditional

加载配置文件

禁用自动配置

添加Filter

集成第三方组件

集成Open API

访问Redis

集成Artemis

集成RabbitMQ

集成Kafka

Spring Cloud开发

项目架构设计

搭建项目框架

设计交易引擎

设计资产系统

设计订单系统

设计撮合引擎

设计清算系统

完成交易引擎

设计定序系统

设计API系统

设计行情系统

设计推送系统

编写UI

项目总结

关注公众号不定期领红包:

加入知识星球社群:

关注微博获取实时动态:

使用Atomic

Last updated: ...

/

Reads: 811276

Edit

Java的java.util.concurrent包除了提供底层锁、并发集合外,还提供了一组原子操作的封装类,它们位于java.util.concurrent.atomic包。

我们以AtomicInteger为例,它提供的主要操作有:

增加值并返回新值:int addAndGet(int delta)

加1后返回新值:int incrementAndGet()

获取当前值:int get()

用CAS方式设置:int compareAndSet(int expect, int update)

Atomic类是通过无锁(lock-free)的方式实现的线程安全(thread-safe)访问。它的主要原理是利用了CAS:Compare and Set。

如果我们自己通过CAS编写incrementAndGet(),它大概长这样:

public int incrementAndGet(AtomicInteger var) {

int prev, next;

do {

prev = var.get();

next = prev + 1;

} while ( ! var.compareAndSet(prev, next));

return next;

}

CAS是指,在这个操作中,如果AtomicInteger的当前值是prev,那么就更新为next,返回true。如果AtomicInteger的当前值不是prev,就什么也不干,返回false。通过CAS操作并配合do ... while循环,即使其他线程修改了AtomicInteger的值,最终的结果也是正确的。

我们利用AtomicLong可以编写一个多线程安全的全局唯一ID生成器:

class IdGenerator {

AtomicLong var = new AtomicLong(0);

public long getNextId() {

return var.incrementAndGet();

}

}

通常情况下,我们并不需要直接用do ... while循环调用compareAndSet实现复杂的并发操作,而是用incrementAndGet()这样的封装好的方法,因此,使用起来非常简单。

在高度竞争的情况下,还可以使用Java 8提供的LongAdder和LongAccumulator。

小结

使用java.util.concurrent.atomic提供的原子操作可以简化多线程编程:

原子操作实现了无锁的线程安全;

适用于计数器,累加器等。

Comments

Make a comment

Sign in to

make a comment

Index

Java教程

Java快速入门

Java简介

安装JDK

第一个Java程序

Java代码助手

使用IDE

使用IDE练习插件

Java程序基础

Java程序基本结构

变量和数据类型

整数运算

浮点数运算

布尔运算

字符和字符串

数组类型

流程控制

输入和输出

if判断

switch多重选择

while循环

do while循环

for循环

break和continue

数组操作

遍历数组

数组排序

多维数组

命令行参数

面向对象编程

面向对象基础

方法

构造方法

方法重载

继承

多态

抽象类

接口

静态字段和静态方法

作用域

内部类

classpath和jar

class版本

模块

Java核心类

字符串和编码

StringBuilder

StringJoiner

包装类型

JavaBean

枚举类

记录类

BigInteger

BigDecimal

常用工具类

异常处理

Java的异常

捕获异常

抛出异常

自定义异常

NullPointerException

使用断言

使用JDK Logging

使用Commons Logging

使用Log4j

使用SLF4J和Logback

反射

Class类

访问字段

调用方法

调用构造方法

获取继承关系

动态代理

注解

使用注解

定义注解

处理注解

泛型

什么是泛型

使用泛型

编写泛型

擦拭法

extends通配符

super通配符

泛型和反射

集合

Java集合简介

使用List

编写equals方法

使用Map

编写equals和hashCode

使用EnumMap

使用TreeMap

使用Properties

使用Set

使用Queue

使用PriorityQueue

使用Deque

使用Stack

使用Iterator

使用Collections

IO

File对象

InputStream

OutputStream

Filter模式

操作Zip

读取classpath资源

序列化

Reader

Writer

PrintStream和PrintWriter

使用Files

日期与时间

基本概念

Date和Calendar

LocalDateTime

ZonedDateTime

DateTimeFormatter

Instant

最佳实践

单元测试

编写JUnit测试

使用Fixture

异常测试

条件测试

参数化测试

正则表达式

正则表达式简介

匹配规则

复杂匹配规则

分组匹配

非贪婪匹配

搜索和替换

加密与安全

编码算法

哈希算法

BouncyCastle

Hmac算法

对称加密算法

口令加密算法

密钥交换算法

非对称加密算法

签名算法

数字证书

多线程

多线程基础

创建新线程

线程的状态

中断线程

守护线程

线程同步

同步方法

死锁

使用wait和notify

使用ReentrantLock

使用Condition

使用ReadWriteLock

使用StampedLock

使用Semaphore

使用Concurrent集合

使用Atomic

使用线程池

使用Future

使用CompletableFuture

使用ForkJoin

使用ThreadLocal

使用虚拟线程

Maven基础

Maven介绍

依赖管理

构建流程

使用插件

模块管理

使用mvnw

发布Artifact

网络编程

网络编程基础

TCP编程

UDP编程

发送Email

接收Email

HTTP编程

RMI远程调用

XML与JSON

XML简介

使用DOM

使用SAX

使用Jackson

使用JSON

JDBC编程

JDBC简介

JDBC查询

JDBC更新

JDBC事务

JDBC Batch

JDBC连接池

函数式编程

Lambda基础

方法引用

使用Stream

创建Stream

使用map

使用filter

使用reduce

输出集合

其他操作

设计模式

创建型模式

工厂方法

抽象工厂

生成器

原型

单例

结构型模式

适配器

桥接

组合

装饰器

外观

享元

代理

行为型模式

责任链

命令

解释器

迭代器

中介

备忘录

观察者

状态

策略

模板方法

访问者

Web开发

Web基础

Servlet入门

Servlet开发

Servlet进阶

重定向与转发

使用Session和Cookie

JSP开发

MVC开发

MVC高级开发

使用Filter

修改请求

修改响应

使用Listener

部署

Spring开发

IoC容器

IoC原理

装配Bean

使用Annotation配置

定制Bean

使用Resource

注入配置

使用条件装配

使用AOP

装配AOP

使用注解装配AOP

AOP避坑指南

访问数据库

使用JDBC

使用声明式事务

使用DAO

集成Hibernate

集成JPA

集成MyBatis

设计ORM

开发Web应用

使用Spring MVC

使用REST

集成Filter

使用Interceptor

处理CORS

国际化

异步处理

使用WebSocket

集成第三方组件

集成JavaMail

集成JMS

使用Scheduler

集成JMX

Spring Boot开发

第一个Spring Boot应用

使用开发者工具

打包Spring Boot应用

瘦身Spring Boot应用

使用Actuator

使用Profiles

使用Conditional

加载配置文件

禁用自动配置

添加Filter

集成第三方组件

集成Open API

访问Redis

集成Artemis

集成RabbitMQ

集成Kafka

Spring Cloud开发

项目架构设计

搭建项目框架

设计交易引擎

设计资产系统

设计订单系统

设计撮合引擎

设计清算系统

完成交易引擎

设计定序系统

设计API系统

设计行情系统

设计推送系统

编写UI

项目总结

廖雪峰的官方网站

©Copyright 2019-2021

Powered by iTranswarp

Feedback

License

原子变量类 深度剖析 AtomicLong CAS longadder - 知乎

原子变量类 深度剖析 AtomicLong CAS longadder - 知乎首发于线程和并发切换模式写文章登录/注册原子变量类 深度剖析 AtomicLong CAS longadder享受生活​参考:《java编程之美》看这篇文章前最好了解过CAS,可阅读java并发 原子性 CAS原理 模拟CAS的实现 CAS的三大问题其实看懂上面这篇文章后基本上自己看源码就ok了。但还是在这里剖析一下。原子变量类是指在java.util.concurrent.atomic这个包里的几个类,比如AtomicBoolean,AtomicInteger这些类,这些类都是使用非阻塞算法CAS实现的。相比于使用锁实现原子性操作这在性能上有很大的提高。这里介绍automiclong类,其他的原理都类似。这里为了防止大家一点都没接触过,不知道这个类有啥用,来看java并发 原子性 CAS原理 模拟CAS的实现 CAS的三大问题 这个链接的前面的代码,体现出了使用原子类和不使用原子类的区别,就不copy过来了。 就关键的就是它保证了读取-修改-写入的原子性,它内部也使用了volatile来保证内存的可见性。这就充分地保证了线程的安全。来看源码: private static final Unsafe unsafe = Unsafe.getUnsafe();//获取unsafe类实例,cas的文章中已经对unsafe类进行了比较详细的讲解。unsafe类就是提供原子性cas的最底层的类了。原子变量类就是使用unsafe进行CAS操作实现原子性的,而原子变量类是在rt.jar包下,也就是说它的直接类加载器就是bootstrap,所以可以直接使用unsafe类。 private static final long valueOffset;//存放value的偏移量,前面讲unsafe类的时候发现,里面很多方法都是传入偏移量进行内存求值的,所以这里有个偏移量。static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); private static native boolean VMSupportsCS8();//判断JVM是否支持long类型无锁CASstatic { try { valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }//获取value在AtomicLong这个类中的偏移量 private volatile long value;//实际的变量值下面来看常用到的主要函数: public final long incrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; }//使用unsafe类实例,原子性设置value值为原始值+1,返回值为递增后的值,也就是++1. public final long getAndIncrement() { return unsafe.getAndAddLong(this, valueOffset, 1L); }//先获得原值,然后加一,返回值为原值,也就是1++;然后我们联系一下前面讲的unsafe类的compareandset方法,其实就是在那个原型上进行修改,把update变为expect+1而已,你自己都会写。。这里从我原文链接复制过来:然后自己理会。public final long getAndSetLong(Object obj,long offset,long update){

long l;

do{

l=getIntvolatile(obj,offset);

}while(!compareAndSwaplong(obj,offset,l,update));

}所以,基本上如果前面把CAS真正看懂了的话,感觉自己就能写出这些原子变量类了。使用atomiclong时,在高并发下大量线程会同时去竞争更新同一个原子变量,但是由于同时只有一个线程的CAS会成功,这就造成了大量线程竞争失败后,会通过无限循环不断尝试自旋尝试CAS操作,而这就会白白浪费了cpu资源。所以就有了longadder的存在。我理解了一波,我觉得longadder的思想就是:比如一个原子变量value,然后有三个cell类,类里面也有value,初始值为0。当低并发情况下直接操作原子变量value,当高并发情况下,就操作3个cell类的value,这样就变成了竞争三个资源,比竞争一个资源要好。然后当要取出value的时候,再把原子变量value和3个cell类里面的value加起来返回。当一个线程对一个cell类的valueCAS不成功的时候,可以去CAS另一个cell类的value。相当于一个任务分成三个任务干,最后再累加起来。这里就不再对源码进行分析了,有点太深了,浅的东西还没学完,到需要的时候再来学这个高级类的源码,现在大概掌握思想先吧。发布于 2018-11-17 23:47高并发Java线程安全​赞同 3​​添加评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录线程

java AtomicLong原理解析 - 程序猿进化之路 - 博客园

java AtomicLong原理解析 - 程序猿进化之路 - 博客园

会员

周边

新闻

博问

AI培训

云市场

所有博客

当前博客

我的博客

我的园子

账号设置

简洁模式 ...

退出登录

注册

登录

程序猿进化之路

进化永无止境

博客园

首页

新随笔

联系

订阅

管理

java AtomicLong原理解析

摘自

http://www.tuicool.com/articles/zuui6z

乐观锁与悲观锁

独占锁是一种悲观锁,synchronized就是一种独占锁,它假设最坏的情况,并且只有在确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。而另一个更加有效的锁就是乐观锁。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

volatile的问题

与锁相比,volatile变量是一和更轻量级的同步机制,因为在使用这些变量时不会发生上下文切换和线程调度等操作,但是volatile变量也存在一些局限:不能用于构建原子的复合操作,因此当一个变量依赖旧值时就不能使用volatile变量。(参考:谈谈volatiile)

Java中的原子操作( atomic operations)

原子操作指的是在一步之内就完成而且不能被中断。原子操作在多线程环境中是线程安全的,无需考虑同步的问题。在java中,下列操作是原子操作:

all assignments of primitive types except for long and double

all assignments of references

all operations of java.concurrent.Atomic* classes

all assignments to volatile longs and doubles

问题来了,为什么long型赋值不是原子操作呢?例如:

long foo = 65465498L;

实时上java会分两步写入这个long变量,先写32位,再写后32位。这样就线程不安全了。如果改成下面的就线程安全了:

private volatile long foo;

因为volatile内部已经做了synchronized.

CAS无锁算法

要实现无锁(lock-free)的非阻塞算法有多种实现方法,其中 CAS(比较与交换,Compare and swap) 是一种有名的无锁算法。CAS, CPU指令,在大多数处理器架构,包括IA32、Space中采用的都是CAS指令,CAS的语义是“我认为V的值应该为A,如果是,那么将V的值更新为B,否则不修改并告诉V的值实际为多少”,CAS是项 乐观锁 技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。CAS无锁算法的C实现如下:

int compare_and_swap (int* reg, int oldval, int newval)

{

ATOMIC();

int old_reg_val = *reg;

if (old_reg_val == oldval)

*reg = newval;

END_ATOMIC();

return old_reg_val;

}

CAS(乐观锁算法)的基本假设前提

CAS比较与交换的伪代码可以表示为:

do{          备份旧数据;         基于旧数据构造新数据;  }while(!CAS( 内存地址,备份的旧数据,新数据 ))  

就是指当两者进行比较时,如果相等,则证明共享数据没有被修改,替换成新值,然后继续往下运行;如果不相等,说明共享数据已经被修改,放弃已经所做的操作,然后重新执行刚才的操作。容易看出 CAS 操作是基于共享数据不会被修改的假设,采用了类似于数据库的 commit-retry 的模式。当同步冲突出现的机会很少时,这种假设能带来较大的性能提升。

JVM对CAS的支持:AtomicInt, AtomicLong.incrementAndGet()

/**

* Atomically increments by one the current value.

*

* @return the previous value

*/  

     private volatile long value //value设置为volatile变量,目的是每次变量的值变更时,其他线程再取该值时,始终为内存中最新的值

public final long getAndIncrement() {    //不加锁,当设置失败时,利用死循环,再次尝试,直至设置成功

while (true) {

long current = get();

long next = current + 1;       //调用compareAndSet方法

if (compareAndSet(current, next))

return current;

}

} /**

* Atomically sets the value to the given updated value

* if the current value {@code ==} the expected value.

*

* @param expect the expected value

* @param update the new value

* @return true if successful. False return indicates that

* the actual value was not equal to the expected value.

*/

public final boolean compareAndSet(long expect, long update) {    //valueOffSet为内存中的值,expect的值为旧的预期值,该线程执行getAndIncrement()函数时,通过get()获取的当时的变量值    //update=expect+1    // 只有valueOffset=expect时才会把变量的值设置为update,设置成功返回true,否则返回false

    return unsafe.compareAndSwapLong(this, valueOffset, expect, update); }

 

二、ABA问题

比如说一个线程one从内存位置V中取出A,这时候另一个线程two也从内存中取出A,并且two进行了一些操作变成了B,然后two又将V位置的数据变成A,这时候线程one进行CAS操作发现内存中仍然是A,然后one操作成功。尽管线程one的CAS操作成功,但是不代表这个过程就是没有问题的。如果链表的头在变化了两次后恢复了原值,但是不代表链表就没有变化。因此前面提到的原子操作AtomicStampedReference/AtomicMarkableReference就很有用了。这允许一对变化的元素进行原子操作。

 

posted @

2015-11-04 16:21 

程序猿进化之路 

阅读(13574) 

评论(0) 

编辑 

收藏 

举报

会员力量,点亮园子希望

刷新页面返回顶部

公告

Copyright © 2024 程序猿进化之路

Powered by .NET 8.0 on Kubernetes