java 对象锁定_少锁定Java对象池
java 對象鎖定
自從我寫任何東西以來已經有一段時間了,我一直在忙于我的新工作,其中涉及在性能調優方面做一些有趣的工作。 挑戰之一是減少應用程序關鍵部分的對象創建。
盡管Java隨著時間的推移已改進了GC算法,但垃圾回收打ic一直是Java的主要難題。 Azul是開發無暫停GC的市場領導者,但Azul JVM并非免費!
創建過多的臨時/垃圾對象并不能很好地工作,因為它為GC創建了工作,并且將對延遲產生負面影響。 過多的垃圾也不能在多核系統上正常工作,因為它會導致緩存污染。
那么我們應該如何解決呢?
垃圾少編碼
僅當您知道需要多少個對象并預先分配它們時,這才有可能,但是實際上很難找到。 但是即使您成功做到了,也必須擔心另一個問題
- 您可能沒有足夠的內存來容納所需的所有對象
- 您還必須處理并發
那么上述問題的解決方案是什么
有一種對象池設計模式可以解決以上兩個問題。 它使您可以指定池中所需的許多對象,并處理并發請求以服務所請求的對象。
對象池一直是許多具有低延遲要求的應用程序的基礎。 Flyweight設計模式是對象池的一種風格。
上面的兩種模式都將幫助我們避免創建對象。 太好了,因此現在減少了GC工作,并且理論上我們的應用程序性能應該得到改善。 實際上,不會那樣做,因為對象池/ Flyweight必須處理并發,并且由于并發問題而失去了避免對象創建而獲得的任何優勢。
處理并發的最常見方法是什么
對象池是一個典型的生產者/消費者問題,可以使用以下技術來解決:
同步:這是在JDK 1.5之前處理并發的唯一方法。 Apache編寫了一個基于同步的出色的對象池 API
鎖: Java在JDK 1.5之后增加了對并發編程的出色支持。 已經有一些使用鎖來開發對象池的工作,例如, furious-objectpool
無鎖:我找不到使用完全無鎖技術構建的任何實現,但是furious-objectpool使用ArrayBlocking隊列和ConcurrentLinked隊列的混合
衡量績效
在此測試中,我創建了一個包含100萬個對象的池,并且這些對象可以通過不同的池實現進行訪問,這些對象將從池中取出并返回到池中。
該測試首先從1個線程開始,然后增加線程數以衡量不同池在爭用情況下的執行情況
- X軸–螺紋數
- Y軸–以毫秒為單位的時間–越短的時間越好
該測試包括來自Apache的池,Furious池和基于ArrayBlocking的池
Apache的性能最差,并且隨著線程數量的增加,性能會進一步下降。 原因是Apache池基于大量使用“同步”
其他兩個(基于Furious和ArrayBlocking的池)的性能更好,但是隨著爭用的增加,它們兩者的速度也會降低。
當12個線程試圖訪問該池時,基于ArrayBlocking隊列的池對于100萬個項目大約需要1000毫秒。 內部使用Arrayblocking隊列的憤怒池大約需要1975 ms。
我必須進行更詳細的調查,以找出為什么Furious花費雙倍的時間,因為它也是基于ArrayBlocking隊列的。
數組阻塞隊列的性能不錯,但這是一種基于鎖定的方法。 如果可以實現無鎖池,我們將獲得哪種類型的性能?
鎖免費游泳池
實現無鎖池不是不可能的,但是有點困難,因為您必須處理多個生產者和消費者。
我將實現一個混合池,該池將在生產者端使用鎖定,而在消費者端使用非阻塞技術。
讓我們看一些數字
我使用新的實現(FastPool)進行了相同的測試,它比ArayBlocking隊列快了30%。
30%的改善還不錯,它絕對可以幫助我們實現延遲目標。
是什么讓快速池快速!
我使用了兩種技術來使其快速運行
- 生產者是基于鎖的–使用鎖來管理多個生產者,這與“數組阻止”隊列相同,因此沒什么大不了的。
- 立即發布已發布項目–在使用便宜的內存屏障釋放鎖之前,它會發布元素。 這會有所收獲
- 消費者不受阻礙–使用CAS來實現這一目標,消費者永遠不會因生產者而受到阻礙。 數組阻止隊列阻止使用者,因為它對生產者和使用者使用相同的鎖
- 線程局部以保持值的局部性–線程局部用于獲取最后使用的值,這在很大程度上減少了爭用。
如果您有興趣查看代碼,則可以使用@ FastObjectPool.java
翻譯自: https://www.javacodegeeks.com/2013/07/lock-less-java-object-pool.html
java 對象鎖定
總結
以上是生活随笔為你收集整理的java 对象锁定_少锁定Java对象池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 死亡骑士天赋冰霜加点(魔兽世界冰霜死亡骑
- 下一篇: WinXP系统怎么怎么恢复系统还原xp如