一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java多線程編程中易混淆的3個關鍵字總結

Java多線程編程中易混淆的3個關鍵字總結

2019-12-13 10:42junjie JAVA教程

這篇文章主要介紹了Java多線程編程中易混淆的3個關鍵字總結,本文總結了、volatile、ThreadLocal、synchronized等3個關鍵字,對這幾個容易混淆概念的關鍵字分別做了講解,需要的朋友可以參考下

概述

最近在看《ThinKing In Java》,看到多線程章節時覺得有一些概念比較容易混淆有必要總結一下,雖然都不是新的東西,不過還是蠻重要,很基本的,在開發或閱讀源碼中經常會遇到,在這里就簡單的做個總結。

1.volatile

volatile主要是用來在多線程中同步變量。

在一般情況下,為了提升性能,每個線程在運行時都會將主內存中的變量保存一份在自己的內存中作為變量副本,但是這樣就很容易出現多個線程中保存的副本變量不一致,或與主內存的中的變量值不一致的情況。

而當一個變量被volatile修飾后,該變量就不能被緩存到線程的內存中,它會告訴編譯器不要進行任何移出讀取和寫入操作的優化,換句話說就是不允許有不同于“主”內存區域的變量拷貝,所以當該變量有變化時,所有調用該變量的線程都會獲得相同的值,這就確保了該變量在應用中的可視性(當一個任務做出了修改在應用中必須是可視的),同時性能也相應的降低了(還是比synchronized高)。

但需要注意volatile只能確保操作的是同一塊內存,并不能保證操作的原子性。所以volatile一般用于聲明簡單類型變量,使得這些變量具有原子性,即一些簡單的賦值與返回操作將被確保不中斷。但是當該變量的值由自身的上一個決定時,volatile的作用就將失效,這是由volatile關鍵字的性質所決定的。

所以在volatile時一定要謹慎,千萬不要以為用volatile修飾后該變量的所有操作都是原子操作,不再需要synchronized關鍵字了。

2.ThreadLocal

首先ThreadLocal和本地線程沒有一毛錢關系,更不是一個特殊的Thread,它只是一個線程的局部變量(其實就是一個Map),ThreadLocal會為每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。這樣做其實就是以空間換時間的方式(與synchronized相反),以耗費內存為代價,單大大減少了線程同步(如synchronized)所帶來性能消耗以及減少了線程并發控制的復雜度。

個人覺得比較典型的例子就是在Android關于Looper的源碼中對ThreadLocal的使用,同時也包含了ThreadLocal的基本用法,具體代碼如下:

  1. public class Looper {  
  2. private static final String TAG = "Looper"
  3.   
  4. // sThreadLocal.get() will return null unless you've called prepare().  
  5. private static final ThreadLocal sThreadLocal = new ThreadLocal();  
  6.   
  7. ......  
  8.   
  9. private static Looper mMainLooper = null;  
  10.   
  11. ......  
  12.   
  13. public static final void prepare() {  
  14.   if (sThreadLocal.get() != null) {  
  15.     throw new RuntimeException("Only one Looper may be created per thread");  
  16.   }  
  17.   sThreadLocal.set(new Looper());  
  18. }  
  19.   
  20. ......  
  21.   
  22. public static final void prepareMainLooper() {  
  23.   prepare();  
  24.   setMainLooper(myLooper());  
  25.   
  26.   ......  
  27.   
  28. }  
  29.   
  30. private synchronized static void setMainLooper(Looper looper) {  
  31.   mMainLooper = looper;  
  32. }  
  33. public synchronized static final Looper getMainLooper() {  
  34.   return mMainLooper;  
  35. }  
  36.   
  37. ......  
  38.   
  39. public static final Looper myLooper() {  
  40.   return (Looper)sThreadLocal.get();  
  41. }  
  42.   
  43. ......  
  44.   

但需要注意的是,雖然ThreadLocal和Synchonized都用于解決多線程并發訪問,ThreadLocal與synchronized還是有本質的區別。synchronized是利用鎖的機制,使變量或代碼塊在某一時該只能被一個線程訪問。而ThreadLocal為每一個線程都提供了變量的副本,使得每個線程在某一時間訪問到的并不是同一個對象,這樣就隔離了多個線程對數據的數據共享。而Synchronized卻正好相反,它用于在多個線程間通信時能夠獲得數據共享。即Synchronized用于線程間的數據共享,而ThreadLocal則用于線程間的數據隔離。所以ThreadLocal并不能代替synchronized,Synchronized的功能范圍更廣(同步機制)。

3.synchronized

synchronized關鍵字是Java利用鎖的機制自動實現的,一般有同步方法和同步代碼塊兩種使用方式。Java中所有的對象都自動含有單一的鎖(也稱為監視器),當在對象上調用其任意的synchronized方法時,此對象被加鎖(一個任務可以多次獲得對象的鎖,計數會遞增),同時在線程從該方法返回之前,該對象內其他所有要調用類中被標記為synchronized的方法的線程都會被阻塞。當然針對每個類也有一個鎖(作為類的Class對象的一部分),所以你懂的^.^。

最后需要注意的是synchronized是同步機制中最安全的一種方式,其他的任何方式都是有風險的,當然付出的代價也是最大的。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲成片在线看 | 99久久免费看精品国产一区 | porno中国xxxxx| nxgx国产| 青青草99热这里都是精品 | 日韩成人精品 | 欧美一级视频在线高清观看 | 天生奶水1v1高h | 香蕉久草在线 | 精品国产福利在线观看一区 | 午夜亚洲视频 | 经典千人斩一区二区视频 | 日产国产精品亚洲系列 | 香蕉久久一区二区三区 | 久久亚洲精品AV无码四区 | 国内精品91最新在线观看 | 日本xxx在线观看免费播放 | 欧美高清乌克兰精品另类 | 欧美视频在线播放观看免费福利资源 | 久久不射网 | 99久久精品免费精品国产 | 草逼网站视频 | 美女靠逼免费视频 | 99久久国产综合精品女小说 | 日韩日日操| 香蕉视频久久 | 日日操综合 | 天天做天天爱天天爽综合网 | 成年人天堂| 午夜影院c绿象 | 2021精品国夜夜天天拍拍 | 亚洲精品成人A8198A片漫画 | 欧美一区二区三区精品影视 | 欧美日韩在线观看区一二 | 男同桌扒开女同桌胸罩喝奶 | 日韩手机在线观看 | 国产精品第2页 | 啊哈用力cao我 | 国产欧美一区二区三区久久 | 日本无卡码一区二区三区 | 91香蕉小视频 |