国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

破除java神話之原子操作都是線程安全的

2019-11-18 10:47:31
字體:
來源:轉載
供稿:網友

  java中原子操作是線程安全的論調經常被提到。根據定義,原子操作是不會被打斷地的操作,因此被認為是線程安全的。實際上有一些原子操作不一定是線程安全的。
  
  這個問題出現的原因是盡量減少在代碼中同步要害字。同步會損害性能,雖然這個損失因JVM不同而不同。另外,在現代的JVM中,同步的性能正在逐步提高。盡管如此,使用同步仍然是有性能代價的,并且程序員永遠會盡力提高他們的代碼的效率,因此這個問題就延續了下來。
  
  在java中,32位或者更少位數的賦值是原子的。在一個32位的硬件平臺上,除了double和long型的其它原始類型通常都是使用32位進行表示,而double和long通常使用64位表示。另外,對象引用使用本機指針實現,通常也是32位的。對這些32位的類型的操作是原子的。
  
  這些原始類型通常使用32位或者64位表示,這又引入了另一個小小的神話:原始類型的大小是由語言保證的。這是不對的。java語言保證的是原始類型的表數范圍而非JVM中的存儲大小。因此,int型總是有相同的表數范圍。在一個JVM上可能使用32位實現,而在另一個JVM上可能是64位的。在此再次強調:在所有平臺上被保證的是表數范圍,32位以及更小的值的操作是原子的。
  
  那么,原子操作在什么情況下不是線程安全的?主要的一點是他們也許確實是線程安全的,但是這沒有被保證!java線程答應線程在自己的內存區保存變量的副本。答應線程使用本地的私有拷貝進行工作而非每次都使用主存的值是為了提高性能。考慮下面的類:
  
  
  class RealTimeClock
  {
   PRivate int clkID;
   public int clockID()
   {
   return clkID;
   }
   public void setClockID(int id)
   {
   clkID = id;
   }
  //...
  }
  
  現在考慮RealTimeClock的一個實例以及兩個線程同時調用setClockID和clockID,并發生以下的事件序列:
  
  T1 調用setClockID(5)
  T1將5放入自己的私有工作內存
  T2調用setClockID(10)
  T2將10放入自己的私有工作內存
  T1調用clockID,它返回5
  5是從T1的私有工作內存返回的
  
  對clockI的調用應該返回10,因為這是被T2設置的,然而返回的是5,因為讀寫操作是對私有工作內存的而非主存。賦值操作當然是原子的,但是因為JVM答應這種行為,因此線程安全不是一定的,同時,JVM的這種行為也不是被保證的。
  
  兩個線程擁有自己的私有拷貝而不和主存一致。假如這種行為出現,那么私有本機變量和主存一致必須在以下兩個條件下:
  
  1、變量使用volatile聲明
  2、被訪問的變量處于同步方法或者同步塊中
  
  假如變量被聲明為volatile,在每次訪問時都會和主存一致。這個一致性是由java語言保證的,并且是原子的,即使是64位的值。(注重很多JVM沒有正確的實現volatile要害字。你可以在www.javasoft.com找到更多的信息。)另外,假如變量在同步方法或者同步塊中被訪問,當在方法或者塊的入口處獲得鎖以及方法或者塊退出時釋放鎖是變量被同步。
  使用任何一種方法都可以保證ClockID返回10,也就是正確的值。變量訪問的頻度不同則你的選擇的性能不同。假如你更新很多變量,那么使用volatile可能比使用同步更慢。記住,假如變量被聲明為volatile,那么在每次訪問時都會和主存一致。與此對照,使用同步時,變量只在獲得鎖和釋放鎖的時候和主存一致。但是同步使得代碼有較少的并發性。
  
  假如你更新很多變量并且不想有每次訪問都和主存進行同步的損失或者你因為其它的原因想排除并發性時可以考慮使用同步。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 伊宁市| 普宁市| 安徽省| 醴陵市| 德令哈市| 镇康县| 安平县| 建水县| 象山县| 澄城县| 阿拉善右旗| 凤台县| 肇东市| 兴义市| 嵩明县| 柯坪县| 昭觉县| 南召县| 巴林右旗| 应用必备| 肃宁县| 三门峡市| 漾濞| 湘阴县| 静宁县| 达拉特旗| 江山市| 黑龙江省| 翁源县| 长寿区| 璧山县| 松溪县| 门源| 连山| 合山市| 清河县| 武陟县| 富蕴县| 汝城县| 集贤县| 陵水|