多線程--基礎篇2--同步

在兩個線程共賣100張票的時候,也會出現問題,同時賣同一張票。

程序如下:

public class TestThread implements Runnable{
         private int j=100;
         public void run(){
               for(int i = 0 ;i<100;i++){
                    if(j>0){
                         try {
                              Thread.sleep(300);//注意這裏休眠了300毫秒
                         } catch (InterruptedException e) {
                               e.printStackTrace();
                         }
                         System.out.println("賣第"+j+"張票!");
                          j--;   
                    }
                 }
             }
}

 public static void main(String[] args) {
          TestThread m=new TestThread();
          new Thread(m).start();
          new Thread(m).start();
 }


結果:

賣第100張票!
賣第100張票!
賣第98張票!
賣第98張票!

......

造成此問題的根本原因在於,判斷剩餘票數和修改票數之間加入了延遲操作。

如果想解決這樣一個問題,就必須使用同步,所謂的同步就是指多個操作在同一時間段內只能有一個線程進行,其他線程要等待此線程完成之後纔可以繼續執行。

在Java中可以通過同步代碼的方法進行代碼的加鎖操作,同步的實現由兩種方式:同步代碼塊和同步方法

1. 同步代碼塊:使用synchronized關鍵字進行同步代碼塊的聲明,但是在使用此操作時必須明確的指出到底要鎖定的是哪個對象,一般都是以當前對象爲主:

synchronized(對象){//一般都是將this進行鎖定

    需要同步的代碼;

}

使用同步代碼塊修改之前的程序:

public class TestThread implements Runnable{
     private int j=100;
     public void run(){
          for(int i = 0 ;i<100;i++){
               synchronized (this) {//同步代碼塊,要將if判斷條件包括在其中,否則會出現賣出第0張票的問題
                  if(j>0){
                      try {
                           Thread.sleep(300);
                      } catch (InterruptedException e) {
                            e.printStackTrace();
                      }
                      System.out.println("賣第"+j+"張票!");
                      j--; 
                  }
             }
         }
    }
}


2. 同步方法:將要同步的代碼塊抽取成方法

public class TestThread implements Runnable {
     private int j = 100;

     public void run() {
          for (int i = 0; i < 100; i++) {
               sale();
          }
     }
     public synchronized void sale() {//同步方法
         if (j > 0) {
           try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("賣第" + j + "張票!");
            j--;
        }
     }
}

 

發佈了32 篇原創文章 · 獲贊 16 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章