線程池知識
參考:【http://www.reibang.com/p/87bff5cc8d8c】
線程池提交
通過Executor.execute()方法提交的任務(wù)坯认,必須實現(xiàn)Runnable接口贸伐,該方式提交的任務(wù)不能獲取返回值,因此無法判斷任務(wù)是否執(zhí)行成功嗽冒。
通過ExecutorService.submit()方法提交的任務(wù)议慰,可以獲取任務(wù)執(zhí)行完的返回值狮含,必須繼承Runnable 接口
#######虛假喚醒 (平時用不到) spurious wakeup
一個線程能在沒有被通知帮坚、中斷或超時的情況下喚醒踩身,也即所謂的“虛假喚醒”
待解決:為什么 wait 方法必須放在 while 循環(huán)體內(nèi)執(zhí)行?
題外話:Netty的一個坑
因為 Netty 里面吐句,其核心的 Future 接口實現(xiàn)中胁后,犯了一個基本的邏輯錯誤,在實現(xiàn) cancel 和 isDone 方法是違反了 JDK 的約定蕴侧。
java中規(guī)定如果調(diào)用了 cancel 方法择同,那么再調(diào)用 isDone 將永遠(yuǎn)返回 true。
在netty中 在調(diào)用了 cancel 方法后净宵,再次調(diào)用 isDone 方法,返回的確是 false裹纳。
futuretask中使用的是cas鎖 UNSAFE里面都是native c實現(xiàn)
Synchronized
https://blog.csdn.net/tongdanping/article/details/79647337
1.使用synchronized修飾非靜態(tài)方法或者使用synchronized修飾代碼塊時制定的為實例對象時择葡,同一個類的不同對象擁有自己的鎖,因此不會相互阻塞剃氧。
2.使用synchronized修飾類和對象時敏储,由于類對象和實例對象分別擁有自己的監(jiān)視器鎖,因此不會相互阻塞朋鞍。
3.使用使用synchronized修飾實例對象時已添,如果一個線程正在訪問實例對象的一個synchronized方法時妥箕,其它線程不僅不能訪問該synchronized方法,該對象的其它synchronized方法也不能訪問更舞,因為一個對象只有一個監(jiān)視器鎖對象畦幢,但是其它線程可以訪問該對象的非synchronized方法。
4.線程A訪問實例對象的非static synchronized方法時缆蝉,線程B也可以同時訪問實例對象的static synchronized方法宇葱,因為前者獲取的是實例對象的監(jiān)視器鎖,而后者獲取的是類對象的監(jiān)視器鎖刊头,兩者不存在互斥關(guān)系黍瞧。
monitorenter
monitorexit
指令
mark word被分成兩部分,lock word和標(biāo)志位原杂。
匯編印颤?還是java字節(jié)碼
偏向鎖:方法的對象頭中加入線程id。如果下次訪問不變則不需要進(jìn)行CAS操作進(jìn)行加鎖和解鎖(因為CAS原子指令雖然相對于重量級鎖來說開銷比較小但還是存在非炒┮蓿可觀的本地延遲)年局。
輕量級鎖:CAS
重量級鎖:當(dāng)鎖處于這個狀態(tài)下,其他線程試圖獲取鎖都會被阻塞住被碗,當(dāng)持有鎖的線程釋放鎖之后會喚醒這些線程某宪。
升級機(jī)制
偏向鎖==》輕量級鎖 另一個線程要求該對象時發(fā)現(xiàn)發(fā)現(xiàn)方法頭里面的線程沒有掛掉
輕量級鎖==》重量級鎖 輕量級鎖cas自旋好多次后發(fā)現(xiàn)還是在自旋或者有另一個對象來競爭 (自旋也是消耗cpu的)
會升級但不會降級 除了偏向鎖可以被設(shè)置為無鎖模式
自旋鎖:為了防止頻繁的掛起和恢復(fù)線程導(dǎo)致的時間消耗
volatile
http://www.reibang.com/p/d3fda02d4cae
volatile是基于Memory Barrier實現(xiàn)的。
這意味著锐朴,如果寫入一個volatile變量a兴喂,可以保證:
1、一個線程寫入變量a后焚志,任何線程訪問該變量都會拿到最新值衣迷。
2、在寫入變量a之前的寫入操作酱酬,其更新的數(shù)據(jù)對于其他線程也是可見的壶谒。因為Memory Barrier會刷出cache中的所有先前的寫入。
LockSupport
出現(xiàn)之前都是用的wait notify
但是wait和notify/notifyAll方法只能在同步代碼塊里用
多次執(zhí)行后膳沽,我們會發(fā)現(xiàn):有的時候能夠正常打印結(jié)果并退出程序汗菜,但有的時候線程無法打印結(jié)果阻塞住了。原因就在于主線程調(diào)用完notify后挑社,線程A才進(jìn)入wait方法陨界,導(dǎo)致線程A一直阻塞住。由于線程A不是后臺線程痛阻,所以整個程序無法退出菌瘪。
那如果換做LockSupport呢?LockSupport就支持主線程先調(diào)用unpark后阱当,線程A再調(diào)用park而不被阻塞嗎俏扩?是的糜工,沒錯。
小結(jié)一下录淡,LockSupport比Object的wait/notify有兩大優(yōu)勢:
LockSupport不需要在同步代碼塊里 捌木。所以線程間也不需要維護(hù)一個共享的同步對象了,實現(xiàn)了線程間的解耦赁咙。
unpark函數(shù)可以先于park調(diào)用钮莲,所以不需要擔(dān)心線程間的執(zhí)行的先后順序。
多次調(diào)用unpark方法與一次調(diào)用結(jié)果是一樣的彼水,都是講_counter賦值為一崔拥。
https://blog.csdn.net/zyzzxycj/article/details/90268381
AtomicInteger
i++線程不安全 因為不是原子性操作
原子類相比于普通的鎖,粒度更細(xì)凤覆、效率更高(除了高度競爭的情況下)
如何把普通變量升級為原子變量链瓦?主要是AtomicIntegerFieldUpdater<T>類
AtomicInteger是lock free AtomicInteger 主要是依賴于 sun.misc.Unsafe 提供的一些 native 方法保證操作的原子性。
ABA問題:AtomicStampedReference
JDK 1.5 以后的 AtomicStampedReference 類就提供了此種能力盯桦,其中的 compareAndSet 方法就是首先檢查當(dāng)前值是否等于預(yù)期值慈俯,判斷的標(biāo)準(zhǔn)就是當(dāng)前引用和郵戳分別和預(yù)期引用和郵戳相等,如果全部相等拥峦,則以原子方式設(shè)置為給定的更新值贴膘。
其實就是多版本控制
AQS
不僅支持獨占模式 同時支持共享模式下的同步實現(xiàn)
函數(shù)分為三類:
1.類似acquire(int)的一類是最基本的一類,不可中斷
2.類似acquireInterruptibly(int)的一類可以被中斷
3.類似tryAcquireNanos(int, long)的一類不僅可以被中斷略号,而且可以設(shè)置阻塞時間
獨占模式下只有當(dāng)tryAcquire返回true的時候我們才能確定獲得資源了刑峡,而在共享模式下,只要tryAcquireShared返回值大于等于0就可以說明獲得資源了玄柠,突梦。
ReentrantLock
基于AQS實現(xiàn) 獨占鎖 可重入鎖
重入性表現(xiàn)在同一個線程可以多次獲得鎖
公平鎖和非公平鎖 =隊列和搶占
公平鎖:每個線程獲取鎖的過程是公平的,等待時間最長的會最先被喚醒獲取鎖羽利。
非公平鎖:同等優(yōu)先級的競爭 無所謂誰先等待 失敗的繼續(xù)等待
條件變量Condition :很大一個程度上是為了解決Object.wait/notify/notifyAll難以使用的問題宫患。
Synchronized中,所有的線程都在同一個object的條件隊列上等待这弧。而ReentrantLock中娃闲,每個condition都維護(hù)了一個條件隊列。
每一個Lock可以有任意數(shù)據(jù)的Condition對象匾浪,Condition是與Lock綁定的畜吊,所以就有Lock的公平性特性:如果是公平鎖,線程為按照FIFO的順序從Condition.await中釋放户矢,如果是非公平鎖,那么后續(xù)的鎖競爭就不保證FIFO順序了殉疼。
Condition接口定義的方法梯浪,await對應(yīng)于Object.wait捌年,signal對應(yīng)于Object.notify,signalAll對應(yīng)于Object.notifyAll挂洛。特別說明的是Condition的接口改變名稱就是為了避免與Object中的wait/notify/notifyAll的語義和使用上混淆礼预。
Java同步器
https://blog.csdn.net/DengDeng_G/article/details/79041134
包括了信號量(Semaphore)、計數(shù)栓(CountDownLatch)虏劲、循環(huán)屏障(CyclicBarrier)托酸、交換器(Exchanger)、Phaser
AQS框架也是同步器
https://blog.csdn.net/DengDeng_G/article/details/79041134
Phaser同步器沒看懂
CountDownLatch面試題
8.10 騰訊面試問題
1.redis+mysql超賣問題如何解決
2.hbase底層架構(gòu)和組成
4.線程池核心參數(shù)
忘了說不同線程池參數(shù)的不同
long keepAliveTime,TimeUnit unit,這個兩個也忘了說
4.線程池阻塞隊列滿了之后的三種情況
5.hashmap和concurrenthashmap區(qū)別
6.如何了解新的技術(shù)
7.AQS
http://www.reibang.com/p/853b203a8d93
https://blog.csdn.net/python8989/article/details/113666420
面試官問我了AQS 我說這個底層其實就是CAS 函數(shù)有tryaquire() tryaquireShared() 但其實不對 應(yīng)該更細(xì)節(jié)的把AQS底層邏輯都講一下 包括自旋鎖 還有node隊列柒巫,對于隊列的操作 非公平鎖和公平鎖 還有l(wèi)ocksupport
需要看一下公平鎖非公平鎖釋放和獲取 lock和release的源碼
注意:AQS里有node syn繼承AQS也有 ReentrantLock使用的AQS中的
http://www.reibang.com/p/4358b1466ec9
AQS中node【https://blog.csdn.net/qq_43986945/article/details/101345713】