Java多線程中的競爭條件、鎖以及同步的概念

來源:互聯網
上載者:User

標籤:多線程   線上   關鍵字   str   syn   其他   條件   列印   操作   

競爭條件

1.競爭條件:

在java多線程中,當兩個或以上的線程對同一個資料進行操作的時候,可能會產生“競爭條件”的現象。這種現象產生的根本原因是因為多個線程在對同一個資料進行操作,此時對該資料的操作是非“原子化”的,可能前一個線程對資料的操作還沒有結束,後一個線程又開始對同樣的資料開始進行操作,這就可能會造成資料結果的變化未知。

package com.huojg.test;public class TestThread {            public static void main(String[] args) {          // new 出一個新的對象 t          MyThread t = new MyThread();          /**          * 兩個線程是在對同一個對象進行操作          */          Thread ta = new Thread(t, "Thread-A");          Thread tb = new Thread(t, "Thread-B");          ta.start();          tb.start();      }  }    class MyThread implements Runnable {      // 變數 a 被兩個線程共同操作,可能會造成線程競爭      int a = 10;      @Override      public void run() {          for (int i = 0; i < 5; i++) {              a -= 1;              try {                  Thread.sleep(1);              } catch (InterruptedException e) {}              System.out.println(Thread.currentThread().getName() + " → a = " + a);          }      }  }  

結果顯示:

Thread-A → a = 8Thread-B → a = 8Thread-A → a = 6Thread-B → a = 6Thread-B → a = 4Thread-A → a = 4Thread-B → a = 2Thread-A → a = 2Thread-A → a = 0Thread-B → a = 0

從上面的結果中我們可以看到,線上程A對資料進行了操作之後,他還沒有來得及資料進行下一次的操作,此時線程B也對資料進行了操作,導致資料a一次性被減了兩次,以至於a為9的時候的值根本沒有列印出來,a為0的時候卻被列印了兩次。

那麼,我們要如何才能避免結果這種情況的出現呢?

2.線程鎖

如果在一個線程對資料進行操作的時候,禁止另外一個線程操作此資料,那麼,就能很好的解決以上的問題了。這種操作叫做給線程加鎖。

package com.huojg.test;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * 在Java多線程中,當兩個或以上的線程對同一個資料進行操作的時候,可能會產生“競爭條件”的現象。這種現象產生的根本原因是因為多個線程在對同一個資料進行操作,此時對該資料的操作是非“原子化”的, * 可能前一個線程對資料的操作還沒有結束,後一個線程又開始對同樣的資料開始進行操作,這就可能會造成資料結果的變化未知。 *  *  * 2.線程鎖如果在一個線程對資料進行操作的時候,禁止另外一個線程操作此資料,那麼,就能很好的解決以上的問題了。這種操作叫做給線程加鎖。 * */public class TestThread {            public static void main(String[] args) {          // new 出一個新的對象 t          MyThread t = new MyThread();          /**          * 兩個線程是在對同一個對象進行操作          */          Thread ta = new Thread(t, "Thread-A");          Thread tb = new Thread(t, "Thread-B");          ta.start();          tb.start();      }  }    class MyThread implements Runnable {      // 聲明鎖      private Lock lock = new ReentrantLock();      // 變數 a 被兩個線程共同操作,可能會造成線程競爭      int a = 10;      @Override      public void run() {            // 加鎖          lock.lock();          for (int i = 0; i < 5; i++) {              a -= 1;              try {                  Thread.sleep(1);              } catch (InterruptedException e) {}              System.out.println(Thread.currentThread().getName() + " → a = " + a);          }          lock.unlock();    }  }  

 

運行結果:

Thread-A → a = 9Thread-A → a = 8Thread-A → a = 7Thread-A → a = 6Thread-A → a = 5Thread-B → a = 4Thread-B → a = 3Thread-B → a = 2Thread-B → a = 1Thread-B → a = 0

上面的代碼給出了給線程枷鎖的方式,可以看到,線上程對資料進行操作之前先給此操作加一把鎖,那麼在此線程對資料進行操作的時候,其他的線程無法對此資料進行操作,只能“阻塞”在一邊等待當前線程對資料操作結束後再對資料進行下一次的操作,當前線程在資料的操作完成之後會解開當前的鎖以便下一個線程操作此資料

用synchronized關鍵字加鎖來對方法進行加鎖:結果一樣;

 

總結:

Java中的多線程,當多個線程對一個資料進行操作時,可能會產生“競爭條件”的現象,這時候需要對線程的操作進行加鎖,來解決多線程操作一個資料時可能產生問題。加鎖方式有兩種,一個是申明Lock對象來對語句快進行加鎖,另一種是通過synchronized 關鍵字來對方法進行加鎖。以上兩種方法都可以有效解決Java多線程中存在的競爭條件的問題。

 

Java多線程中的競爭條件、鎖以及同步的概念

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.