JAVA併發編程學習筆記------多線程調優

1. 多線程場景下儘可能使用併發容器代替同步容器java

  (如ConcurrentHashMap代替同步且基於散列的Map, 遍歷操做爲主要操做的狀況下用CopyOnWriteArrayList代替同步的List)數組

  ConcurrentHashMap:分段鎖機制,多線程條件下優於HashMap+synchronized的組合方式;
  CopyOnWriteArrayList: 每次修改時都會建立並從新發佈一個新的容器副本,從而實現可變性。容器的迭代器保留一個指向底層基礎數組的引用,這個數組當前位於迭代器的起始位置,因爲他不會被修改,
因此在對其進行同步時只需確保數組內容的可見性。
2. 避免死鎖
  a)儘可能不要在釋放鎖以前競爭其餘鎖:通常能夠經過細化同步方法來實現,只在真正須要保護共享資源的地方去拿鎖,並儘快釋放鎖,這樣能夠有效下降在同步方法裏調用其餘同步方法 的狀況
  b)順序索取鎖資源: 若是實在沒法避免嵌套索取鎖資源,則須要制定一個索取鎖資源的策略,先規劃好有哪些鎖,而後各個線程按照一個順序去索取
  c)嘗試定時鎖: Java 5提供了更靈活的鎖工具,能夠顯式地索取和釋放鎖。那麼在索取鎖的時候能夠設定一個超時時間,若是超過這個時間還沒索取到鎖,則不會繼續堵塞而是放棄這次任務,以下:安全

public boolean trySendOnSharedLine(String message, long timeout, TimeUnit unit) throws InterruptedException {
   	long nanosToLock = unit.toNanos(timeout) - estimatedNanosToSend(message);
    	if (!lock.tryLock(nanosToLock, NANOSECONDS)){
       		return false;
	}
   	 try {
        	return sendOnSharedLine(message);
   	} finally {
       		lock.unlock();
    	}
} 

這樣能夠效打破死鎖條件。
3. Amdahl定理:
  speedup<= 1/(F+(1-F)/N)
  其中,F是串行化比例,N是處理器數量,由上可知,只有儘量減小串行化,才能最大化地提升可擴展能力。下降串行化的關鍵就是下降鎖競爭,當不少並行任務掛在鎖的獲取上,就是串行化的表現.
4. 下降鎖競爭
  1)縮小鎖的範圍
    儘可能縮小鎖保護的範圍,快進快出,所以儘可能不要直接在方法上使用synchronized關鍵字,而只是在真正須要線程安全保護的地方使用
  2)減少鎖的粒度
    儘可能避免大段的synchronize代碼塊
  3)減小共享資源的依賴
    在多線程開發中儘可能減小對共享資源的依賴,好比對象池的技術應該慎重考慮,新的JVM對新建對象以作了足夠的優化,性能很是好,若是用對象池不但不能提升多少性能,反而 會由於鎖競爭致使下降線程的可併發性。
  4)使用讀寫分離鎖來替換獨佔鎖
    Java 5提供了一個讀寫分離鎖(ReadWriteLock)來實現讀-讀併發,讀-寫串行,寫-寫串行的特性。這種方式更進一步提升了可併發性,由於有些場景大部分是讀操做,所以不必串行工做。
5. 切換上下文
  線程比較多的時候,操做系統切換線程上下文的性能消耗是不能忽略的,
6. 內存同步
  當使用到synchronized、volatile或Lock的時候,都會爲了保證可見性致使更多的內存同步,這就沒法享受到JMM結構帶來了性能優化。
7. 適當使用同步工具類
  (1) 閉鎖(CountDownLatch): 延遲線程的進度直到其達到終止狀態,用來確保某些活動直到其餘活動都完成後才繼續執行;一次性對象,一旦進入終止狀態,就不能被重置;
  (2) FutureTask: 可生成結果的Callable,若是有結果可用,那麼FutureTask.get將當即返回結果,不然它會一直阻塞,直到結果計算出來再將其返回。
  (3) 信號量(Semaphore):用來控制同時訪問某個特定資源的操做數量,或者同時某個指定操做的數量,Semaphore還能夠用來實現某種資源池,或者對容器施加邊界。
  (4) 柵欄(Barrier): 相似於閉鎖,區別在於全部線程必須同時到達柵欄位置才能繼續執行,閉鎖用於等待事件,而柵欄用於等待其餘線程。可被重置用於下次使用。兩種實現方式:CyclicBarrier,Exchanger性能優化

 8. 實際狀況中,應儘量的使用現有的線程安全對象(例如AtomicInteger)來管理類的狀態多線程

 9. 在多線程程序中使用共享且可變的long和double等類型的變量也是不安全的,除非用volatile來聲明它們,或者用鎖保護起來。併發

相關文章
相關標籤/搜索