Java高併發8-計算機內存模式以及volatile,sychronized工做原理

1、複習

  • threadLocals是不具備繼承性的
  • inheritableThreadLocal類是具備繼承性的。
  • Thread類的部分源碼解析

2、多CPU的好處

  • 減小線程上下文切換的開銷

3、 計算機的內存模型

  • 一塊主內存,而後被多個線程所調用,每一個線程又有本身的一級緩存,線程共享了二級緩存
  • 出現的問題:一級緩存是每一個線程本身獨有的,運行的時候,會先去一級緩存裏面找,若是沒有再去二級緩存,最後去內存,因此若是多個線程對一個共享變量操做的話,就會致使一級緩存裏放置的數據是過時的,所以會產生問題。
  • 下面這張圖是一個計算機架構模型
8.1
8.1
  • 每一個核心都有本身的控制器和計算器,控制器又包含一組寄存器和操做控制器。
  • 因爲cache的存在會致使內存不可見問題。
  • synchronized關鍵字是Java提供的一種原子性內置鎖,Java內置的使用者看不到的鎖叫作內部鎖,又稱爲監視器鎖。線程的執行代碼在進入到synchronied語句的時候,會自動獲取內部鎖,這時候,若是其餘線程若是想要獲取該共享對象就會進入阻塞狀態,除非原線程釋放鎖,或者拋出異常,或者原線程調用了wait方法主動釋放了該鎖,其餘線程才能拿到資源。
  • 內置鎖是一中排他鎖,也就是當一個線程釋放了鎖以後,其餘線程才能取得這把鎖。

1.爲何synchronized性能低下

  • 由於使用synchronized會形成上下文切換,容易形成多線程阻塞。

2.線程一致性

  • Java中的線程是與操做系統的原生線程是一一對應的,因此當一個線程阻塞的時候,須要從用戶態切換到內核態來執行阻塞操做。

3.synchronized實現基本原理

  • 一切操做都是基於內存中的數據來進行的,基本上cache中的數據過期性問題就不存在,老是取內存中的最新數據,老是把最新數據刷新到內存中去。

4、volatile關鍵字

  • 使用該關鍵字,基本實現和synchronized一致,都是直接讀內存而不是讀取線程的工做內存,而且刷新值也是直接刷新到內存。
package com.ruigege.OtherFoundationOfConcurrent2;

public class ThreadNotSafeInteger {

 private int value;

 public int getValue() {
  return value;
 }

 public void setValue(int value) {
  this.value = value;
 }
 

 
}

  • 上面的代碼是不安全的,下面舉兩個線程安全的例子
package com.ruigege.OtherFoundationOfConcurrent2;

public class ThreadSafeInteger1 {
 private int value;

 public synchronized int getValue() {
  return value;
 }

 public synchronized void setValue(int value) {
  this.value = value;
 }
 

}

package com.ruigege.OtherFoundationOfConcurrent2;

public class ThreadSafeInteger2 {

 private volatile int value;

 public int getValue() {
  return value;
 }

 public void setValue(int value) {
  this.value = value;
 }
 
 
}

5、源碼:

相關文章
相關標籤/搜索