2018第24周總結
本周寫了AQS原理及相關應用的學習摘錄。它是高級Java開發應該掌握的基礎,雖然在當前浮躁的社會背景下,知道這些原理對實際的工作、對個人工作中創造的價值可能沒大的影響。學習並在工作中模仿應用這裏面設計、思想,可以讓你在未來的技術路上走的更遠。
AQS與重入鎖ReetrantLock原理
AQS共享鎖應用之Semaphore原理
讀寫鎖 ReentrantReadWriteLock
AQS目的是為構建同步鎖、同步組件提供基礎框架,原理是通過volatile int型變量抽象同步狀態,變量值為0表示鎖空閑,正數值表示鎖占用,然後通過內部類Node構建FIFO的同步隊列實現等待獲取同步狀態的線程排隊工作,通過內部類ConditionObject構建條件等待隊列,完成等待條件線程的排隊工作。
AQS設計上、采用模板方法模式構建,其內部提供了並發操作的核心方法、而將一些不同模式下實現可能有差異的操作定義為模板方法,讓其子類實現。如ReentrantLock通過內部類Sync及其子類繼承AQS實現tryAcuire()和tryRelease()方法來實現獨占鎖,而SemaPhore則通過內部類繼承AQS實現tryAcquireShared()方法和tryReleaseShared()方法實現共享模式鎖。
讀寫鎖裏面同時包含了共享鎖【讀鎖】和排他鎖【寫鎖】,為此它在基於AQS實現時,擴展了同步狀態變量的意義,用這個狀態高位部分表示讀鎖,低位表示寫鎖。由於讀鎖是共享鎖會有多個,要把線程重入讀鎖的次數保存在ThreadLocal變量裏,而寫鎖低16位可以表示寫鎖的重入次數。
讀寫鎖多用在讀多寫少的場景,而這也是大部分現實生活中的應用場景,就像我們每個人日常都是讀多寫少一樣。同樣在容器實現為避免使用鎖,進一步提高效率,可以使用CopyOnWrite策略,JDK本身有提供它的實現,默認容器只能讀,但有寫操作時復制一份而不是加鎖控制,它在多讀寫少的場景下能提高程序運行效率,但它不能做到實時一致性,並且會占用更多的內存。
java並發之阻塞隊列LinkedBlockingQueue與ArrayBlockingQueue
講了這兩種阻塞的隊列的實現原理及差異。由於底層數據結構前者用鏈表後者用數組,所以前者可以用兩個鎖和兩個條件【對put和take分別加鎖,提高了吞吐率,但put速度大於take速度時可能會造成內存溢出要多註意】,後者使用了一個鎖和兩個條件【對put、take操作使用排它鎖控制,同時有兩個條件notEmpty和notFull來實現put、take操作的阻塞和喚醒控制】。
2018第24周總結