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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java 自旋方法_JAVA循环使用CAS实现自旋操作

發布時間:2025/3/11 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 自旋方法_JAVA循环使用CAS实现自旋操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

大家碰到了實現一個線程安全的計數器的需求改怎么做呢?根據經驗你應該知道我們要在多線程中實現共享變量的原子性和可見性問題,于是鎖成為一個不可避免的話題,下文討論的是與之對應的無鎖CAS。

為什么要無鎖

我們一想到在多線程下保證安全的方式,肯定是鎖,不管從硬件、操作系統層面都或多或少在使用鎖。鎖有優缺點嗎?

使用鎖就需要獲得鎖、釋放鎖,CPU需要通過上下文切換和調度管理來進行這個操作,對于一個獨占鎖,一個線程在持有鎖后沒有執行結束,其他線程就必須等待,等到前面的線程執行完畢,CPU就會把鎖拿出來給其他線程來搶了。鎖的這種概念基于一種悲觀機制,它總是認為數據會被修改,所以,你在操作一部分代碼塊之前先加一把鎖,操作完成后再釋放,這樣就安全了。

什么是 CAS

比較并交換(compare and swap,CAS),是原子操作的一種,可用于在多線程編程中實現不被打斷的數據交換操作,從而避免多線程同時改寫某一數據時由于執行順序不確定性以及中斷的不可預知性產生的數據不一致性問題。該操作通過將內存中的值與指定的數據進行比較,當數值一樣時,將內存中的數據替換成新值。

JAVA如何實現

package com.concurrent.program;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {

private AtomicInteger atomicI = new AtomicInteger(0);

private int i = 0;

public static void main(String[] args) {

final Counter cas = new Counter();

Listts = new ArrayList(10);

long start = System.currentTimeMillis();

for (int j=0;j < 100; j++){

Thread t = new Thread(new Runnable() {

@Override

public void run() {

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

cas.count();

cas.safeCount();

}

}

});

ts.add(t);

}

for (Thread t : ts) {

t.start();

}

//等待所有線程執行完成

for (Thread t:ts){

try {

t.join();

} catch (InterruptedException e){

e.printStackTrace();

}

}

System.out.println(cas.i);

System.out.println(cas.atomicI.get());

System.out.println(System.currentTimeMillis() - start);

}

/**

* 使用CAS實現線程安全計數器

*/

private void safeCount(){

for(;;){

int i = atomicI.get();

boolean suc = atomicI.compareAndSet(i, ++i);

if (suc) {

break;

}

}

}

/**

* 非線程安全計數器

*/

private void count(){

i++;

}

}

以上代碼實現了一個基于CAS線程安全的計數器方法safeCount和一個非線程安全的計數器方法count,讀者可以自行運行,運行結果如下:

非線程安全計數器: 971850

使用CAS實現線程安全計數器:?1000000

執行時間:78ms

CAS存在的問題

1.ABA問題。因為CAS需要在操作值的時候,檢查值有沒有發生變化,如果沒有則更新。但是如果原來一個值是A,變成了B,又變成A,那么使用CAS進行檢查時會發現它的值沒有發生變化,但是實際發生了變化了。ABA解決問題的思路就是使用版本號。在變量前面追加版本號,每次變量更新的時候把版本號加1,那么A→B→A就會變成1A→2B→3A。從JAVA1.5開始,JDK的Atomic包里提供了一個類AtomicStampedReference來解決ABA問題。

2.循環時間長,開銷大。CAS長時間不成功,會給CPU帶來非常大的執行開銷。如果JVM能支持處理器提供的pause指令,那么效率會有一定的提示。

3.只能保證一個共享變量的原子操作。對多個共享變量操作時,CAS可以把多個共享變量合并成一個共享變量來操作。比如,有兩個共享變量i=2,j=a,合并成ij=2a,然后用CAS來操作ij。從JAVA1.5開始,JDK的Atomic包里面提供了一個類AtomicReference類來保證引用對象之間的原子性,就可以把多個變量放在一個對象里面來進行CAS操作。

總結

以上是生活随笔為你收集整理的java 自旋方法_JAVA循环使用CAS实现自旋操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。