JAVA學習筆記之 多執行緒賣票

weixin_33912445發表於2016-11-22
  • 多執行緒程式出現安全問題的原因:
    A:是多執行緒程式。
    B:有共享資料。
    C:針對共享資料有多條語句操作。

  • 現在的程式存在著問題,所以,我們要改進該程式,讓它沒有問題。
    怎麼改進呢?
    只需要把多執行緒環境中,操作共享資料的操作給變成單執行緒的就沒有問題了。

  • Java針對這種情況,就提供了同步技術:同步程式碼塊。
    格式:
    synchronized(物件) {
    需要被同步的程式碼。
    }

     A:物件?
         如果不知道用哪個物件,就用Object物件。
     B:需要被同步的程式碼?
         哪些程式碼導致出現了問題,就把哪些程式碼給同步起來。
    
     哪些程式碼會出問題呢?
         有共享資料。
         針對共享資料有多條語句操作。
    
  • 加入同步後,居然還有問題,為什麼呢?
    同步程式碼塊中的物件針對多個執行緒必須是同一個。
    其實這個物件被稱為同步鎖物件。

  • 同步程式碼塊的鎖物件是誰?
    任意物件

  • 同步方法的鎖物件是誰?
    this物件

  • 靜態方法的鎖物件是誰?
    類.class 位元組碼檔案物件
    當前類的位元組碼檔案

  • 程式碼如下

public static void main(String[] args) {
    Ticket t = new Ticket();

    Thread t1 = new Thread(t, "視窗1");
    Thread t2 = new Thread(t, "視窗2");
    Thread t3 = new Thread(t, "視窗3");
    Thread t4 = new Thread(t, "視窗4");

    t1.start();
    t2.start();
    t3.start();
    t4.start();
}

Ticket的類 ----- 同步鎖

public class Ticket implements Runnable {
private int tickets = 100;
private Object obj = new Object();

@Override
public void run() {
    while (true) {
        // t1,t2,t3,t4
        // tickets=1;
        // 假設t1過來,看到synchronized,就知道下面的程式碼被同步了。
        // 看到obj就知道這是鎖物件。假設t1進去前,obj這個鎖物件表示開的狀態。
        synchronized (obj) {
            // t1進來,就把鎖物件的狀態改為關的狀態。
            if (tickets > 0) {
                try {
                    Thread.sleep(10);// t1睡下了
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()
                        + "正在出售第" + (tickets--) + "張票");
            }
        }
        // t1出來了,你們繼續搶,我也還可以搶。
    }
}

}

Ticket的類 ----- Lock鎖

public class Ticket implements Runnable {
public int  ticks = 100;

//定義lock鎖物件
private Lock lock = new ReentrantLock();

@Override
public void run() {

    lock.lock();
    
    if (ticks > 0) {
        
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println(Thread.currentThread().getName() + "正在出售第" + (ticks--) + "張票");
    }
    
    //釋放鎖
    lock.unlock();
}
}

相關文章