【1】鎖
1、加鎖的機制
參見:java線程安全和鎖機制詳解
網(wǎng)址:http://smallbug-vip./blog/2275743
2、鎖的機制有如下問題
(1)在多線程環(huán)境下,加鎖、釋放鎖會導(dǎo)致比較多的上下文切換和調(diào)度延時,從而引起性能問題。
(2)一個線程持有鎖會導(dǎo)致其他所有需要此鎖的線程掛起。
(3)如果一個優(yōu)先級高的線程等待一個優(yōu)先級低的線程釋放鎖會導(dǎo)致優(yōu)先級倒置,引起性能風(fēng)險。
3、悲觀鎖和樂觀鎖
(1)獨占鎖:是一種悲觀鎖,synchronized就是一種獨占鎖,會導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。
樂觀鎖:每次不加鎖,假設(shè)沒有沖突去完成某項操作,如果因為沖突失敗就重試,直到成功為止。
(2)volatile是不錯的機制,但是volatile不能保證原子性。因此,對于同步問題最終還是要回到鎖機制上來。
【優(yōu)質(zhì)文章】深入理解Java內(nèi)存模型(四)——volatile:http://www./lib/view/open1459412319988.html
【2】CAS方法:CompareAndSwap
1、樂觀鎖的使用的機制就是CAS。
在CAS方法中,CAS有三個操作數(shù),內(nèi)存值V,舊的預(yù)期值E,要修改的新值U。當(dāng)且僅當(dāng)預(yù)期值E和內(nèi)存值V相等時,將內(nèi)存值V修改為U,否則什么都不做。
2、非阻塞算法(nonblocking algorithms):一個線程的失敗或者掛起不應(yīng)該影響其他線程的失敗或掛起的算法。
(1)非阻塞算法簡介:https://www.ibm.com/developerworks/cn/java/j-jtp04186/
(2)非阻塞算法通常叫作樂觀算法,因為它們繼續(xù)操作的假設(shè)是不會有干擾。如果發(fā)現(xiàn)干擾,就會回退并重試。
3、CAS方法
(1)CompareAndSwap()就使用了非阻塞算法來代替鎖定。
(2)舉例:AtomicInteger來研究在沒有鎖的情況下是如何做到數(shù)據(jù)正確性的。
在沒有鎖機制的情況下,要保證線程間的數(shù)據(jù)是可見的,就會常常用到volatile原語了。
private volatile int value;
可使用如下方法讀取內(nèi)存變量值value:
public final int getValue(){
return value;
}
遞增計數(shù)器是如何實現(xiàn)的:
public final int incrementAndGet(){
for(;;){
int current = getValue();
int next = value + 1;
if(compareAndSet(current,next)){
return next;
}
}
}
該方法采用了CAS操作,每次從內(nèi)存中讀取數(shù)據(jù)然后將此數(shù)據(jù)和+1后的結(jié)果進(jìn)行CAS操作,如果成功就返回結(jié)果,否則重試直到成功為止。
而compareAndSet操作利用了Java本地接口(JNI,Java Native Interface)完成CPU指令的操作:
public final boolean compareAndSet(int expect, int update){
return unsafe.compareAndSwapInt(this,valueOffset,expect,unsafe);
}
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(*.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex); }
}
【3】“ABA”問題
1、可以發(fā)現(xiàn),CAS實現(xiàn)的過程是先取出內(nèi)存中某時刻的數(shù)據(jù),在下一時刻比較并替換,那么在這個時間差會導(dǎo)致數(shù)據(jù)的變化,此時就會導(dǎo)致出現(xiàn)“ABA”問題。
2、什么是”ABA”問題?
比如說一個線程one從內(nèi)存位置V中取出A,這時候另一個線程two也從內(nèi)存中取出A,并且two進(jìn)行了一些操作變成了B,然后two又將V位置的數(shù)據(jù)變成A,這時候線程one進(jìn)行CAS操作發(fā)現(xiàn)內(nèi)存中仍然是A,然后one操作成功。
盡管線程one的CAS操作成功,但是不代表這個過程就是沒有問題的。
【4】用AtomicStampedReference/AtomicMarkableReference解決ABA問題
1、原子操作:http://www./xylz/archive/2010/07/02/325079.html
2、用AtomicStampedReference解決ABA問題:http://blog./2011/09/resolve-aba-by-atomicstampedreference.html
3、高并發(fā)Java(4):無鎖: http://www./21282.html
4、AtomicStampedReference、AtomicMarkableReference源碼分析,解決cas ABA問題: https://blog.csdn.net/zqz_zqz/article/details/68062568
5、關(guān)于AtomicStampedReference使用的坑: https://blog.csdn.net/xybz1993/article/details/79992120
6、JAVA中的CAS: https://blog.csdn.net/mmoren/article/details/79185862
7、看看別人的Java面試 你是否又有學(xué)習(xí)的動力了?: http://www./software/707.html
注:以上內(nèi)容均來自網(wǎng)絡(luò),該內(nèi)容僅作為學(xué)習(xí)參考
|