CAS閮戒笉浜嗚В锛屼綘杩樻€庝箞鐪婮.U.C
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAS閮戒笉浜嗚В锛屼綘杩樻€庝箞鐪婮.U.C相关的知识,希望对你有一定的参考价值。
鏍囩锛?a href='http://www.mamicode.com/so/1/%e7%a1%ac%e4%bb%b6' title='纭欢'>纭欢 util 璁剧疆 string exception safe exec 鏁版嵁 his
鍓嶈█璇村埌CAS锛圕ompareAndSwap锛夛紝涓嶅緱涓嶅厛璇翠竴璇?strong>鎮茶閿?/strong>鍜?strong>涔愯閿?/strong>锛屽洜涓篊AS鏄箰瑙傞攣鎬濇兂鐨勪竴绉嶅疄鐜般€?/p>
鎮茶閿?/strong>锛氭€绘槸寰堟偛瑙傜殑璁や负锛屾瘡娆℃嬁鏁版嵁閮戒細鏈夊叾浠栫嚎绋嬪苟鍙戞墽琛岋紝鎵€浠ユ瘡娆¢兘浼氳繘琛屽姞閿侊紝鐢ㄥ畬涔嬪悗閲婃斁閿侊紝鍏朵粬鐨勭嚎绋嬫墠鑳芥嬁鍒伴攣锛岃繘鑰屾嬁鍒拌祫婧愯繘琛屾搷浣溿€俲ava涓殑synchronized鍜孯eentrantLock绛夌嫭鍗犻攣灏辨槸鎮茶閿佹€濇兂鐨勫疄鐜般€?/p>
涔愯閿?/strong>锛氭€绘槸寰堜箰瑙傝涓猴紝鑷繁鎷垮埌鏁版嵁鎿嶄綔鐨勬椂鍊欙紝娌℃湁鍏朵粬绾跨▼鏉ュ苟鍙戞搷浣滐紝绛夎嚜宸辨搷浣滅粨鏉熻鏇存柊鏁版嵁鏃讹紝鍒ゆ柇鑷繁瀵规暟鎹搷浣滅殑鏈熼棿鏈夋病鏈夊叾浠栫嚎绋嬭繘琛屾搷浣滐紝濡傛灉鏈夛紝鍒欒繘琛岄噸璇曪紝鐩村埌鎿嶄綔鍙樻洿鎴愬姛銆備箰瑙傞攣甯镐娇鐢–AS鍜岀増鏈彿鏈哄埗鏉ュ疄鐜般€俲ava涓?strong>java.util.atomic鍖呬笅鐨勫師瀛愮被閮芥槸鍩轰簬CAS瀹炵幇鐨勩€?/p>
CAS鎸?strong>CompareAndSwap涓€銆佷粈涔堟槸CAS
CAS涓湁涓変釜鍙橀噺锛氬唴瀛樺湴鍧€V锛屾湡寰呭€糀, 鏇存柊鍊糂銆?/p>
褰撲笖浠呭綋鍐呭瓨鍦板潃V瀵瑰簲鐨勫€间笌鏈熷緟鍊糀鏃剁浉绛夋椂锛屽皢鍐呭瓨鍦板潃V瀵瑰簲鐨勫€兼洿鎹负B銆?/strong>
浜屻€乤tomic鍖?/h3>
鏈変簡鎮茶閿侊紝涔愯閿佺殑鐭ヨ瘑锛岃鎴戜滑璧拌繘java.util.atomic鍖咃紝鐪嬩竴鐪媕ava涓瑿AS鐨勫疄鐜般€?/p>
杩欏氨鏄?strong>java.util.atomic鍖呬笅鐨勭被锛屾垜浠潃閲嶇湅AtomicInteger婧愮爜锛堝叾浠栫殑閮芥槸涓€鏍风殑鎬濇兂瀹炵幇鐨勶級
鐒跺悗鎬濊€僀AS鏈変粈涔堝紛绔紵濡備綍瑙e喅寮婄锛熸湁浠€涔堜紭缂虹偣锛?/strong>
2.1銆佽蛋杩汚tomicInteger婧愮爜
public class AtomicInteger extends Number implements java.io.Serializable {
private static final long serialVersionUID = 6214790243416807050L;
// 浣跨敤Unsafe.compareAndSwapInt杩涜鍘熷瓙鏇存柊鎿嶄綔
private static final Unsafe unsafe = Unsafe.getUnsafe();
//value瀵瑰簲鐨勫瓨鍌ㄥ湴鍧€鍋忕Щ閲? private static final long valueOffset;
static {
try {
//浣跨敤鍙嶅皠鍙妘nsafe.objectFieldOffset鎷垮埌value瀛楁鐨勫唴瀛樺湴鍧€鍋忕Щ閲忥紝杩欎釜鍊兼槸鍥哄畾涓嶅彉鐨? valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
//volatile淇グ鐨勫叡浜彉閲? private volatile int value;
//..........
}
涓婇潰鐨勪唬鐮佸叾瀹炲氨鏄负浜嗗垵濮嬪寲鍐呭瓨鍊煎搴旂殑鍐呭瓨鍦板潃鍋忕Щ閲弙alueOffset锛屾柟渚垮悗缁墽琛孋AS鎿嶄綔鏃朵娇鐢ㄣ€傚洜涓鸿繖涓€间竴鏃﹀垵濮嬪寲锛屽氨涓嶄細鏇存敼锛屾墍浠ヤ娇鐢╯tatic final 淇グ銆?/p>
鎴戜滑鍙互鐪嬪埌value浣跨敤浜唙olatile淇グ锛屽叾涓篃璇翠簡volatile鐨勮涔夈€?/p>
鎴戜滑閮界煡閬撳鏋滆繘琛寁alue++鎿嶄綔锛屽苟鍙戜笅鏄笉瀹夊叏鐨勩€備笂涓€绡囦腑鎴戜滑涔熼€氳繃渚嬪瓙璇佹槑浜唙olatile鍙兘淇濊瘉鍙鎬э紝涓嶈兘淇濊瘉鍘熷瓙鎬с€傚洜涓?strong>value++鏈韩涓嶆槸鍘熷瓙鎿嶄綔锛寁alue++鍒嗕簡涓夋锛屽厛鎷垮埌value鐨勫€硷紝杩涜+1锛屽啀璧嬪€煎洖value銆?/p>
2.2銆乧ompareAndSwapXxx
鎴戜滑鍏堢湅涓€鐪婣tomicInteger鎻愪緵鐨凜AS鎿嶄綔銆?/p>
/**
* 鍘熷瓙鍦板皢value璁剧疆涓簎pdate锛屽鏋渧alueOffset瀵瑰簲鐨勫€间笌expect鐩哥瓑鏃? *
* @param expect 鏈熷緟鍊? * @param update 鏇存柊鍊? * @return 濡傛灉鏇存柊鎴愬姛锛岃繑鍥瀟rue;鍦╲alueOffset瀵瑰簲鐨勫€间笌expect涓嶇浉绛夋椂杩斿洖false
*/
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
鎴戜滑宸茬粡鐭ラ亾CAS鐨勫師鐞嗭紝閭f潵鐪嬬湅涓嬮潰鐨勬祴璇曘€?strong>浣犵煡閬撹緭鍑虹殑缁撴灉鏄灏戝悧锛?/strong>璇勮鍖虹粰鍑轰綘鐨勭瓟妗堝惂銆?/p>
public class AtomicIntegerTest {
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger();
atomicInteger.compareAndSet(0, 1);
atomicInteger.compareAndSet(2, 1);
atomicInteger.compareAndSet(1, 3);
atomicInteger.compareAndSet(2, 4);
System.out.println(atomicInteger.get());
}
}
Unsafe鎻愪緵浜嗕笁涓師瀛愭洿鏂扮殑鏂规硶銆?/p>
鍏充簬Unsafe绫伙紝鍥犱负java涓嶆敮鎸佺洿鎺ユ搷浣滃簳灞傜‖浠惰祫婧愶紝濡傚垎閰嶅唴瀛樼瓑銆傚鏋滀綘浣跨敤unsafe寮€杈熺殑鍐呭瓨锛屾槸涓嶈JVM鍨冨溇鍥炴敹绠$悊锛岄渶瑕佽嚜宸辩鐞嗭紝瀹规槗閫犳垚鍐呭瓨娉勬紡绛夈€?/strong>
2.3銆丄tomicInteger鐨勫師瀛愯嚜澧炴柟娉?/h4>
鎴戜滑涓婇潰璇翠簡锛寁alue++涓嶆槸鍘熷瓙鎿嶄綔锛屼笉鑳藉湪骞跺彂涓嬩娇鐢ㄣ€傛垜浠潵鐪嬬湅AtomicInteger鎻愪緵鐨勫師瀛?+鎿嶄綔銆?/p>
/**
* 鍘熷瓙鍦板value杩涜+1鎿嶄綔
*
* @return 杩斿洖鏇存柊鍚庣殑鍊? */
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}
/**
* unsafe鎻愪緵鐨勬柟娉? * var1 鏇存敼鐨勭洰鏍囧璞? * var2 鐩爣瀵硅薄鐨勫叡浜瓧娈靛搴旂殑鍐呭瓨鍦板潃鍋忕Щ閲弙alueOffset
* var4 闇€瑕佸湪鍘焩alue涓婂鍔犵殑鍊? * @return 杩斿洖鏈洿鏂板墠鐨勫€? */
public final int getAndAddInt(Object var1, long var2, int var4) {
//鏈熷緟鍊? int var5;
do {
//鑾峰彇valueOffset瀵瑰簲鐨剉alue鐨勫€硷紝鏀寔volatile load
var5 = this.getIntVolatile(var1, var2);
//濡傛灉鍘熷瓙鏇存柊澶辫触锛屽垯涓€鐩撮噸璇曪紝鐩村埌鎴愬姛銆? } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
鎴戜滑鐪嬪埌CAS鍙兘鍘熷瓙鐨勬洿鏂颁竴涓€硷紝濡傛灉鎴戜滑瑕佸師瀛愭洿鏂板涓€硷紝CAS鍙互鍋氬埌鍚楋紵绛旀鏄彲浠ョ殑銆?/p>
2.4銆丄tomicReference
濡傛灉瑕佸師瀛愬湴鏇存柊澶氫釜鍊硷紝灏遍渶瑕佷娇鐢?strong>AtomicReference銆傚叾浣跨敤鐨勬槸compareAndSwapObject鏂规硶銆傚彲浠ュ皢澶氫釜鍊煎皝瑁呭埌涓€涓璞′腑锛屽師瀛愬湴鏇存崲瀵硅薄鏉ュ疄鐜板師瀛愭洿鏂板涓€笺€?/p>
public class MultiValue {
private int value1;
private long value2;
private Integer value3;
public MultiValue(int value1, long value2, Integer value3) {
this.value1 = value1;
this.value2 = value2;
this.value3 = value3;
}
}
public class AtomicReferenceTest {
public static void main(String[] args) {
MultiValue multiValue1 = new MultiValue(1, 1, 1);
MultiValue multiValue2 = new MultiValue(2, 2, 2);
MultiValue multiValue3 = new MultiValue(3, 3, 3);
AtomicReference<MultiValue> atomicReference = new AtomicReference<>();
//鍥犱负鏋勯€燗tomicReference鏃讹紝娌℃湁浣跨敤鏈夊弬鏋勯€犲嚱鏁帮紝鎵€浠alue榛樿鍊兼槸null
atomicReference.compareAndSet(null, multiValue1);
System.out.println(atomicReference.get());
atomicReference.compareAndSet(multiValue1, multiValue2);
System.out.println(atomicReference.get());
atomicReference.compareAndSet(multiValue2, multiValue3);
System.out.println(atomicReference.get());
}
}
//杈撳嚭缁撴灉
//MultiValue{value1=1, value2=1, value3=1}
//MultiValue{value1=2, value2=2, value3=2}
//MultiValue{value1=3, value2=3, value3=3}
鎴戜滑鍐嶇湅涓€鐪婣tomicReference鐨刢ompareAndSet鏂规硶銆?/p>
娉ㄦ剰锛?strong>杩欓噷鐨勬瘮杈冮兘鏄娇鐢?=鑰岄潪equals鏂规硶銆傛墍浠ユ渶濂藉皝瑁呯殑MultiValue涓嶈鎻愪緵set鏂规硶銆?/p>
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
2.5銆丆AS鐨凙BA闂
鍋囪浣犵殑璐︽埛涓婃湁100鍧楅挶锛屼綘瑕佺粰濂崇エ杞?0鍧楅挶銆?/strong>
鎴戜滑浣跨敤CAS杩涜鍘熷瓙鏇存柊璐︽埛浣欓銆傜敱浜庢煇绉嶅師鍥狅紝浣犵涓€娆$偣鍑昏浆璐﹀嚭鐜伴敊璇紝浣犱互涓烘病鏈夊彂璧疯浆璐﹁姹傦紝杩欐椂鍊欎綘鍙堢偣鍑讳簡涓€娆°€傜郴缁熷紑鍚簡涓や釜绾跨▼杩涜杞处鎿嶄綔锛岀涓€涓嚎绋嬭繘琛孋AS姣旇緝锛屽彂鐜颁綘鐨勮处鎴蜂笂棰勬湡鏄?00鍧楅挶锛屽疄闄呬篃鏈?00鍧楅挶锛岃繖鏃跺€欒浆璧颁簡50锛岄渶瑕佽缃负100 - 50 = 50 鍏冿紝杩欐椂璐︽埛浣欓涓?0
绗竴涓嚎绋嬫搷浣滄垚鍔熶簡锛岀浜屼釜绾跨▼鐢变簬鏌愮鍘熷洜闃诲浣忎簡锛涜繖鏃跺€欙紝浣犵殑瀹朵汉鍙堢粰浣犺浆浜?0鍧楅挶锛屽苟涓旇浆璐︽垚鍔熴€傞偅浣犺处鎴蜂笂鐜板湪鍙堟槸100鍧楅挶锛?/strong>
澶阀浜嗭紝绗簩涓嚎绋嬭鍞ら啋浜嗭紝鍙戠幇浣犵殑璐︽埛鏄?00鍧楅挶锛岃窡棰勬湡鐨?00鏄浉绛夌殑锛岃繖鏃跺€欏張CAS涓?0銆傚ぇ鍏勫紵锛屽摥鎯ㄤ簡锛屼綘绠楃畻锛屾纭殑鍦烘櫙浣犺鏈夊灏戦挶锛?/strong>杩欏氨鏄疌AS瀛樺湪鐨凙BA闂銆?/p>
澶у蹇冩兂锛岄潬锛岃繖涓嶆槸鍧戝悧锛熼偅杩樼敤銆傘€傘€傘€傘€傘€傘€傘€傘€傘€傘€傘€傘€傘€傚喎闈欙紝鍐烽潤銆備綘鑳芥兂鍒扮殑闂锛宩dk閮借兘鎯冲埌銆俛tomic鍖呮彁渚涗簡涓€涓?strong>AtomicStampedReferencepublic class AtomicIntegerABA {
private static AtomicInteger atomicInteger = new AtomicInteger(100);
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
//绾跨▼1
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
atomicInteger.compareAndSet(100, 50);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
});
//绾跨▼2
executorService.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
atomicInteger.compareAndSet(50, 100);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
});
//绾跨▼3
executorService.execute(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
atomicInteger.compareAndSet(100, 50);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get());
});
executorService.shutdown();
}
}
//杈撳嚭缁撴灉
//pool-1-thread-1 - 100
//pool-1-thread-1 - 50
//pool-1-thread-2 - 50
//pool-1-thread-2 - 100
//pool-1-thread-3 - 100
//pool-1-thread-3 - 50
2.6銆丄tomicStampedReference
鐪嬪悕瀛楁槸涓嶆槸璺烝tomicReference寰堝儚鍟婏紝鍏跺疄灏辨槸鍦ˋtomicReference涓?strong>鍔犱笂浜嗕竴涓増鏈彿锛屾瘡娆℃搷浣滈兘瀵圭増鏈彿杩涜鑷锛岄偅姣忔CAS涓嶄粎瑕佹瘮杈僾alue锛岃繕瑕佹瘮杈僺tamp锛屽綋涓斾粎褰撲袱鑰呴兘鐩哥瓑锛屾墠鑳藉杩涜鏇存柊銆?/strong>
public AtomicStampedReference(V initialRef, int initialStamp) {
pair = Pair.of(initialRef, initialStamp);
}
//瀹氫箟浜嗗唴閮ㄩ潤鎬佸唴閮ㄧ被Pair锛屽皢鏋勯€犲嚱鏁板垵濮嬪寲鐨勫€间笌鐗堟湰鍙锋瀯閫犱竴涓狿air瀵硅薄銆?private static class Pair<T> {
final T reference;
final int stamp;
private Pair(T reference, int stamp) {
this.reference = reference;
this.stamp = stamp;
}
static <T> Pair<T> of(T reference, int stamp) {
return new Pair<T>(reference, stamp);
}
}
//鎵€浠ユ垜浠箣鍓嶇殑value灏卞搴斾负鐜板湪鐨刾air
private volatile Pair<V> pair;
璁╂垜浠潵鐪嬩竴鐪嬪畠鐨凜AS鏂规硶銆?/p>
public boolean compareAndSet(V expectedReference,
V newReference,
int expectedStamp,
int newStamp) {
Pair<V> current = pair;
return
//鍙湁鍦ㄦ棫鍊间笌鏃х増鏈彿閮界浉鍚岀殑鏃跺€欐墠浼氭洿鏂颁负鏂板€硷紝鏂扮増鏈彿
expectedReference == current.reference &&
expectedStamp == current.stamp &&
((newReference == current.reference &&
newStamp == current.stamp) ||
casPair(current, Pair.of(newReference, newStamp)));
}
private boolean casPair(Pair<V> cmp, Pair<V> val) {
return UNSAFE.compareAndSwapObject(this, pairOffset, cmp, val);
}
杩樻槸涓婇潰杞处鐨勪緥瀛愶紝鎴戜滑浣跨敤AtomicStampedReference鏉ョ湅鐪嬫槸鍚﹁В鍐充簡鍛€?/p>
public class AtomicStampedReferenceABA {
/**
* 鍒濆鍖栬处鎴蜂腑鏈?00鍧楅挶锛岀増鏈彿瀵瑰簲0
*/
private static AtomicStampedReference<Integer> atomicInteger = new AtomicStampedReference<>(100, 0);
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
int[] result = new int[1];
//绾跨▼1
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
//灏?00鏇存柊涓?0锛岀増鏈彿+1
atomicInteger.compareAndSet(100, 50, 0, 1);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
});
//绾跨▼2
executorService.execute(() -> {
try {
TimeUnit.MILLISECONDS.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
//灏?0鏇存柊涓?00锛岀増鏈彿+1
atomicInteger.compareAndSet(50, 100, 1, 2);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
});
//绾跨▼3
executorService.execute(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
//姝ょ嚎绋嬭繕鏄互涓烘病鏈夊叾浠栫嚎绋嬭繘琛岃繃鏇存敼锛屾墍浠ユ棫鐗堟湰鍙疯繕鏄?
atomicInteger.compareAndSet(100, 50, 0, 1);
System.out.println(Thread.currentThread().getName() + " - " + atomicInteger.get(result));
});
executorService.shutdown();
}
}
//杈撳嚭缁撴灉
//pool-1-thread-1 - 100
//pool-1-thread-1 - 50
//pool-1-thread-2 - 50
//pool-1-thread-2 - 100
//pool-1-thread-3 - 100
//pool-1-thread-3 - 100
濡堝鍐嶄篃涓嶇敤鎷呭績鎴戠殑閽卞皯浜嗐€?/p>
涓夈€佹€荤粨
鏈瘒璇︾粏璁茶В浜咰AS鐨勫師鐞嗭紝CAS鍙互杩涜鍘熷瓙鏇存柊涓€涓€硷紙鍖呮嫭瀵硅薄锛夛紝涓昏鐢ㄤ簬璇诲鍐欏皯鐨勫満鏅紝濡傚師瀛愯嚜澧炴搷浣滐紝濡傛灉澶氱嚎绋嬭皟鐢紝鍦–AS澶辫触涔嬪悗锛屼細姝诲惊鐜竴鐩撮噸璇曪紝鐩村埌鏇存柊鎴愬姛銆傝繖绉嶆儏鍐垫槸寰堣€桟PU璧勬簮鐨勶紝铏界劧娌℃湁閿侊紝浣嗗惊鐜殑鑷棆鍙兘姣旈攣鐨勪唬浠疯繕楂樸€傚悓鏃跺瓨鍦ˋBA闂锛屼絾AtomicStampedReference閫氳繃鍔犲叆鐗堟湰鍙锋満鍒跺凡缁忚В鍐炽€傚叾瀹炲浜巃tomic鍖咃紝jdk1.8鏂板鐨?strong>LongAdder锛屾晥鐜囨瘮AtomicLong楂橈紝9榫欒繕鏈秹瓒筹紝浠ュ悗鑲畾浼氬搧涓€鍝併€侸.U.C锛坖ava.util.concurrent锛夊寘涓ぇ閲忎娇鐢ㄤ簡CAS锛孋oncurrentHashMap涔熶娇鐢ㄥ埌锛屽鏋滀笉浜嗚ВCAS锛屾€庝箞鍏ユ墜J.U.C鍛€?/p>
以上是关于CAS閮戒笉浜嗚В锛屼綘杩樻€庝箞鐪婮.U.C的主要内容,如果未能解决你的问题,请参考以下文章
UI銆佸師鍨嬩笌瀹為檯涓嶇锛涚爺鍙戞€间綘锛屼綘瑕佹€庝箞鍔烇紵-Dotest杞欢娴嬭瘯
棰樺璇濓細2020 骞磋鎬庝箞鐢?Intellij IDEA 鎼缓 Haskell 鐜