日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java atomicinteger_Java多线程进阶(十三)—— J.U.C之atomic框架:AtomicInteger

發(fā)布時間:2024/8/1 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java atomicinteger_Java多线程进阶(十三)—— J.U.C之atomic框架:AtomicInteger 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、AtomicInteger簡介

AtomicInteger,應(yīng)該是atomic框架中用得最多的原子類了。顧名思義,AtomicInteger是Integer類型的線程安全原子類,可以在應(yīng)用程序中以原子的方式更新int值。

1. 創(chuàng)建AtomicInteger對象

先來看下AtomicInteger對象的創(chuàng)建。

AtomicInteger提供了兩個構(gòu)造器,使用默認構(gòu)造器時,內(nèi)部int類型的value值為0:

AtomicInteger atomicInt = new AtomicInteger();

AtomicInteger類的內(nèi)部并不復(fù)雜,所有的操作都針對內(nèi)部的int值——value,并通過Unsafe類來實現(xiàn)線程安全的CAS操作:

2. AtomicInteger的使用

來看下面這個示例程序:

public class Main {

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

AtomicInteger ai = new AtomicInteger();

List list = new ArrayList<>();

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

Thread t = new Thread(new Accumlator(ai), "thread-" + i);

list.add(t);

t.start();

}

for (Thread t : list) {

t.join();

}

System.out.println(ai.get());

}

static class Accumlator implements Runnable {

private AtomicInteger ai;

Accumlator(AtomicInteger ai) {

this.ai = ai;

}

@Override

public void run() {

for (int i = 0, len = 1000; i < len; i++) {

ai.incrementAndGet();

}

}

}

}

上述代碼使用了AtomicInteger的incrementAndGet方法,以原子的操作對int值進行自增,該段程序執(zhí)行的最終結(jié)果為10000(10個線程,每個線程對AtomicInteger增加1000),如果不使用AtomicInteger,使用原始的int或Integer,最終結(jié)果值可能會小于10000(并發(fā)時讀到了過時的數(shù)據(jù)或存在值覆蓋的問題)。

我們來看下incrementAndGet內(nèi)部:

內(nèi)部調(diào)用了Unsafe類的getAndAddInt方法,以原子方式將value值增加1,然后返回增加前的原始值。

注意,上述是JDK1.8的實現(xiàn),在JDK1.8之前,上述方法采用了自旋+CAS操作的方式:

public final int getAndIncrement() {

for (;;) {

int current = get();

int next = current + 1;

if (compareAndSet(current, next))

return current;

}

}

3. AtomicInteger的特殊方法說明

AtomicInteger中有一個比較特殊的方法——lazySet:

lazySet方法是set方法的不可見版本。什么意思呢?

我們知道通過volatile修飾的變量,可以保證在多處理器環(huán)境下的“可見性”。也就是說當一個線程修改一個共享變量時,其它線程能立即讀到這個修改的值。volatile的實現(xiàn)最終是加了內(nèi)存屏障:

保證寫volatile變量會強制把CPU寫緩存區(qū)的數(shù)據(jù)刷新到內(nèi)存

讀volatile變量時,使緩存失效,強制從內(nèi)存中讀取最新的值

由于內(nèi)存屏障的存在,volatile變量還能阻止重排序

lazySet內(nèi)部調(diào)用了Unsafe類的putOrderedInt方法,通過該方法對共享變量值的改變,不一定能被其他線程立即看到。也就是說以普通變量的操作方式來寫變量。

為什么會有這種奇怪方法?什么情況下需要使用lazySet呢?

考慮下面這樣一個場景:

private AtomicInteger ai = new AtomicInteger();

lock.lock();

try

{

// ai.set(1);

}

finally

{

lock.unlock();

}

由于鎖的存在:

lock()方法獲取鎖時,和volatile變量的讀操作一樣,會強制使CPU緩存失效,強制從內(nèi)存讀取變量。

unlock()方法釋放鎖時,和volatile變量的寫操作一樣,會強制刷新CPU寫緩沖區(qū),把緩存數(shù)據(jù)寫到主內(nèi)存

所以,上述ai.set(1)可以用ai.lazySet(1)方法替換:

由鎖來保證共享變量的可見性,以設(shè)置普通變量的方式來修改共享變量,減少不必要的內(nèi)存屏障,從而提高程序執(zhí)行的效率。

二、類/接口說明

類聲明

構(gòu)造器

接口聲明

方法聲明

描述

int accumulateAndGet(int x, IntBinaryOperator accumulatorFunction)

使用IntBinaryOperator 對當前值和x進行計算,并更新當前值,返回計算后的新值

int addAndGet(int delta)

以原子方式將給定值與當前值相加,返回相加后的新值

boolean compareAndSet(int expect, int update)

如果當前值 == expect,則以原子方式將該值設(shè)置為給定的更新值(update)

int decrementAndGet()

以原子方式將當前值減 1,返回新值

int get()

獲取當前值

int getAndAccumulate(int x, IntBinaryOperator accumulatorFunction)

使用IntBinaryOperator 對當前值和x進行計算,并更新當前值,返回計算前的舊值

int getAndAdd(int delta)

以原子方式將給定值與當前值相加,返回舊值

int getAndDecrement()

以原子方式將當前值減 1,返回舊值

int getAndIncrement()

以原子方式將當前值加 1,返回舊值

int getAndSet(int newValue)

以原子方式設(shè)置為給定值,并返回舊值

int getAndUpdate(IntUnaryOperator updateFunction)

使用IntBinaryOperator 對當前值進行計算,并更新當前值,返回計算前的舊值

int incrementAndGet()

以原子方式將當前值加 1,返回新值

void lazySet(int newValue)

設(shè)置為給定值,但不保證值的改變被其他線程立即看到

void set(int newValue)

設(shè)置為給定值

int updateAndGet(IntUnaryOperator updateFunction)

使用IntBinaryOperator 對當前值進行計算,并更新當前值,返回計算后的新值

boolean weakCompareAndSet(int expect, int update)

weakCompareAndSet無法保證除操作目標外的其他變量的執(zhí)行順序( 編譯器和處理器為了優(yōu)化程序性能而對指令序列進行重新排序 ),同時也無法保證這些變量的可見性。

三、其它原子類

與AtomicInteger類似的原子類還有AtomicBoolean和AtomicLong,底層都是通過Unsafe類做CAS操作,來原子的更新狀態(tài)值。可以參考Oracle官方文檔:https://docs.oracle.com/javas...,不再贅述。

總結(jié)

以上是生活随笔為你收集整理的java atomicinteger_Java多线程进阶(十三)—— J.U.C之atomic框架:AtomicInteger的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。