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

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

java線程簡介(共享對數據的訪問)

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

  1、 共享變量
  
  
  要使多個線程在一個程序中有用,它們必須有某種方法可以互相通信或共享它們的結果。
  
  讓線程共享其結果的最簡單方法是使用共享變量。它們還應該使用同步來確保值從一個線程正確傳播到另一個線程,以及防止當一個線程正在更新一些相關數據項時,另一個線程看到不一致的中間結果。
  
  線程基礎中計算素數的示例使用了一個共享布爾變量,用于表示指定的時間段已經過去了。這說明了在線程間共享數據最簡單的形式是:輪詢共享變量以查看另一個線程是否已經完成執行某項任務。
  
  2、存在于同一個內存空間中的所有線程
  
  
  
  正如前面討論過的,線程與進程有許多共同點,不同的是線程與同一進程中的其它線程共享相同的進程上下文,包括內存。這非常便利,但也有重大責任。只要訪問共享變量(靜態或實例字段),線程就可以方便地互相交換數據,但線程還必須確保它們以受控的方式訪問共享變量,以免它們互相干擾對方的更改。
  
  任何線程可以訪問所有其作用域內的變量,就象主線程可以訪問該變量一樣。素數示例使用了一個公用實例字段,叫做 finished,用于表示已經過了指定的時間。當計時器過期時,一個線程會寫這個字段;另一個線程會定期讀取這個字段,以檢查它是否應該停止。注:這個字段被聲明成 volatile,這對于這個程序的正確運行非常重要。在本章的后面,我們將看到原因。
  
  
  3、受控訪問的同步
  
  
  為了確保可以在線程之間以受控方式共享數據,java 語言提供了兩個要害字:synchronized 和 volatile。
  
  Synchronized 有兩個重要含義:它確保了一次只有一個線程可以執行代碼的受保護部分(互斥,mutual exclusion 或者說 mutex),而且它確保了一個線程更改的數據對于其它線程是可見的(更改的可見性)。
  
  假如沒有同步,數據很輕易就處于不一致狀態。例如,假如一個線程正在更新兩個相關值(比如,粒子的位置和速率),而另一個線程正在讀取這兩個值,有可能在第一個線程只寫了一個值,還沒有寫另一個值的時候,調度第二個線程運行,這樣它就會看到一個舊值和一個新值。同步讓我們可以定義必須原子地運行的代碼塊,這樣對于其他線程而言,它們要么都執行,要么都不執行。
  
  同步的原子執行或互斥方面類似于其它操作環境中的臨界段的概念。
  
  
  4、確保共享數據更改的可見性
  
  
  同步可以讓我們確保線程看到一致的內存視圖。
  
  處理器可以使用高速緩存加速對內存的訪問(或者編譯器可以將值存儲到寄存器中以便進行更快的訪問)。在一些多處理器體系結構上,假如在一個處理器的高速緩存中修改了內存位置,沒有必要讓其它處理器看到這一修改,直到刷新了寫入器的高速緩存并且使讀取器的高速緩存無效。
  
  這表示在這樣的系統上,對于同一變量,在兩個不同處理器上執行的兩個線程可能會看到兩個不同的值!這聽起來很嚇人,但它卻很常見。它只是表示在訪問其它線程使用或修改的數據時,必須遵循某些規則。
  
  Volatile 比同步更簡單,只適合于控制對基本變量(整數、布爾變量等)的單個實例的訪問。當一個變量被聲明成 volatile,任何對該變量的寫操作都會繞過高速緩存,直接寫入主內存,而任何對該變量的讀取也都繞過高速緩存,直接取自主內存。這表示所有線程在任何時候看到的 volatile 變量值都相同。
  
  假如沒有正確的同步,線程可能會看到舊的變量值,或者引起其它形式的數據損壞。
  
  
  5、用鎖保護的原子代碼塊
  
  
  Volatile 對于確保每個線程看到最新的變量值非常有用,但有時我們需要保護比較大的代碼片段,如涉及更新多個變量的片段。
  
  同步使用監控器(monitor)或鎖的概念,以協調對特定代碼塊的訪問。
  
  每個 Java 對象都有一個相關的鎖。同一時間只能有一個線程持有 Java 鎖。當線程進入 synchronized 代碼塊時,線程會阻塞并等待,直到鎖可用,當它可用時,就會獲得這個鎖,然后執行代碼塊。當控制退出受保護的代碼塊時,即到達了代碼塊末尾或者拋出了沒有在 synchronized 塊中捕捉的異常時,它就會釋放該鎖。
  
  這樣,每次只有一個線程可以執行受給定監控器保護的代碼塊。從其它線程的角度看,該代碼塊可以看作是原子的,它要么全部執行,要么根本不執行。
  
  6、簡單的同步示例
  
  
  使用 synchronized 塊可以讓您將一組相關更新作為一個集合來執行,而不必擔心其它線程中斷或看到計算的中間結果。以下示例代碼將打印“1 0”或“0 1”。假如沒有同步,它還會打印“1 1”(或“0 0”,隨便您信不信)。
  
  
  public class SyncExample {
   PRivate static lockObject = new Object();
   private static class Thread1 extends Thread {
   public void run() {
   synchronized (lockObject) {
   x = y = 0;
   System.out.println(x);
   }
   }
   }
  
   private static class Thread2 extends Thread {
   public void run() {
   synchronized (lockObject) {
   x = y = 1;
   System.out.println(y);
   }
   }
   }
  
   public static void main(String[] args) {
   new Thread1().run();
   new Thread2().run();
   }
  }
  
  
  在這兩個線程中都必須使用同步,以便使這個程序正確工作。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 淮阳县| 柳河县| 福州市| 伊川县| 崇阳县| 常宁市| 平陆县| 荣昌县| 和平区| 巫山县| 石家庄市| 普兰店市| 舟曲县| 东莞市| 辽中县| 叶城县| 太原市| 庆安县| 都匀市| 阜宁县| 江阴市| 鸡东县| 甘泉县| 荣成市| 福安市| 桦南县| 隆子县| 高要市| 云安县| 沂水县| 同德县| 定南县| 庄浪县| 平乐县| 宽城| 和龙市| 信丰县| 鹤山市| 凤冈县| 石河子市| 吐鲁番市|