volatile:
- 保證可見(jiàn)性
- 不保證原子性
- 禁止指令重排序
為什么不保證原子性窘拯?
因?yàn)楫?dāng)一個(gè)兩個(gè)線程一起寫入工作內(nèi)存的時(shí)候捏雌,一個(gè)線程掛起证鸥,一個(gè)線程寫入措译,當(dāng)寫入的線程通知的時(shí)候缨该,另一個(gè)線程還沒(méi)有來(lái)的及收到通知偎行,就寫入工作內(nèi)存中,所以就沒(méi)有原子性了
單例模式要加volatile來(lái)禁止指令重排
可以用AtomicInteger來(lái)替代
AtomicInteger的底層是CAS
JMM:
- 可見(jiàn)性
- 原子性
- 有序性
CAS:
- unsafe :是CPU的一條并發(fā)原語(yǔ),用內(nèi)存地址偏移量來(lái)修改值蛤袒,直到比較成功才更新成功
- 自旋鎖
缺點(diǎn): - 會(huì)一直自旋熄云,循環(huán)開(kāi)銷大,給cpu導(dǎo)致很大的開(kāi)銷
- 只能對(duì)一個(gè)共享變量進(jìn)行原子性操作
- ABA問(wèn)題:用修改版本號(hào)來(lái)避免AtomicStampedReference
ArrayList:
線程不安全妙真,解決:
- vector 加了synchronize的ArrayList
- Collections.synchronizedList(new ArrayList<>());
- new CopyOnWriteArrayList<>();用了volatile和寫時(shí)復(fù)制
CopyOnWriteArraySet用的也是CopyOnWriteArrayList
原因:一個(gè)同學(xué)在修改的時(shí)候缴允,另一個(gè)同學(xué)過(guò)來(lái)修改,導(dǎo)致并發(fā)異常
HashSet底層是HashMap
他的value是present的一個(gè)Object類
ConcurrentHashMap只會(huì)對(duì)一段數(shù)據(jù)上鎖珍德,而不會(huì)對(duì)整個(gè)map上鎖
公平鎖和非公平鎖
synchronize是非公平鎖
ReentrantLock可以選擇练般,默認(rèn)是非公平鎖
這兩個(gè)鎖都是可重入鎖,可以避免死鎖
自旋就是while循環(huán)加CAS,但是如果自旋鎖太重了锈候,可能會(huì)拖慢系統(tǒng)薄料,因?yàn)榈却木€程一直在自旋。
public class Main {
AtomicReference<Thread> atomicReference = new AtomicReference<>();
public void myLock(){
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName()+" is comming");
while(!atomicReference.compareAndSet(null, thread)){}
}
public void unLock(){
Thread thread = Thread.currentThread();
atomicReference.compareAndSet(thread, null);
System.out.println(Thread.currentThread().getName()+"It's time to unlock");
}
public static void main(String[] args) {
Main main = new Main();
new Thread(()->{
main.myLock();
try{
TimeUnit.SECONDS.sleep(5);
}catch(Exception e){
e.printStackTrace();
}
main.unLock();
}).start();
try{
TimeUnit.SECONDS.sleep(1);
}catch(Exception e){
e.printStackTrace();
}
new Thread(()->{
main.myLock();
try{
TimeUnit.SECONDS.sleep(1);
}catch(Exception e){
e.printStackTrace();
}
System.out.println("------------------");
main.unLock();
}).start();
}
}