線程同步基礎之使用非依賴屬性實現同步

當使用synchronized關鍵字來保護代碼塊時,必須把對象引用做爲傳入參數。一般狀況下,使用this關鍵字來引用執行方法所屬的對象,也可使用其餘的對象對其進行引用。通常來講,這些對象就是爲這個目的而建立的。例如,在類中有兩個非依賴屬性,它們被多個線程共享,你必須同步每個變量的訪問,可是同一時刻只容許一個線程訪問一個屬性變量,其餘某個線程訪問另外一個屬性變量。java

這裏咱們演示電影院售票場景。這個範例模擬了有兩個屏幕和兩個售票處的電影院。一個集票處賣出的一張票,只能用於其中一個屏幕,不能同時用於兩個屏幕,所以每一個電影院的剩餘票數是獨立的屬性。ide

示例:this

package concurrency;

public class Main9 {
    public static void main(String[] args) {
        Cinema cinema = new Cinema();
        TicketOffice1 ticketOffice1 = new TicketOffice1(cinema);
        Thread thread1 = new Thread(ticketOffice1,"TicketOffice1");
        TicketOffice2 ticketOffice2 = new TicketOffice2(cinema);
        Thread thread2 = new Thread(ticketOffice2,"TicketOffice2");
        thread1.start();
        thread2.start();
        try {
            //等待這兩個線程結束!!
            thread1.join();
            thread1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.printf("Room 1 Vacancies:  %d\n", cinema.getVacanciesCinema1());
        System.out.printf("Room 2 Vacancies:  %d\n", cinema.getVacanciesCinerna2());
    }
}

//電影院類
class Cinema{
    private long vacanciesCinema1;
    private long vacanciesCinema2;
    private final Object controlCinema1,controlCinema2;
    public Cinema(){
        controlCinema1 = new Object();
        controlCinema2 = new Object();
        vacanciesCinema1 = 20;
        vacanciesCinema2 = 20;
    }
    public boolean sellTickets1(int number) {
        synchronized (controlCinema1) {
            if(number < vacanciesCinema1){
                vacanciesCinema1 -= number;
                return true;
            }else{
                return false;
            }
        }
    }
    public boolean sellTickets2(int number) {
        synchronized (controlCinema2) {
            if(number < vacanciesCinema2){
                vacanciesCinema2 -= number;
                return true;
            }else{
                return false;
            }
        }
    }
    public boolean returnTickets1(int number){
        synchronized (controlCinema1) {
            vacanciesCinema1 += number;
            return true;
        }
    }
    public boolean returnTickets2(int number){
        synchronized (controlCinema2) {
            vacanciesCinema2 += number;
            return true;
        }
    }
    public long getVacanciesCinema1(){
        return vacanciesCinema1;
    }
    public long getVacanciesCinerna2(){
        return vacanciesCinema2;
    }
}

//售票處1
class TicketOffice1 implements Runnable{
    private Cinema cinema;
    public TicketOffice1(Cinema cinema) {
        this.cinema = cinema;
    }
    //模擬對電影院的操做
    @Override
    public void run() {
        cinema.sellTickets1(3);
        cinema.sellTickets1(2);
        cinema.sellTickets2(2);
        cinema.returnTickets1(3);
        cinema.sellTickets1(5);
        cinema.sellTickets2(2);
        cinema.sellTickets2(2);
    }
}

//售票處2
class TicketOffice2 implements Runnable{
    private Cinema cinema;
    public TicketOffice2(Cinema cinema) {
        this.cinema = cinema;
    }
    //模擬對電影院操做
    @Override
    public void run() {
        cinema.sellTickets2(2);
        cinema.sellTickets2(4);
        cinema.sellTickets1(2);
        cinema.sellTickets1(1);
        cinema.returnTickets2(2);
        cinema.sellTickets1(3);
        cinema.sellTickets2(2);
        cinema.sellTickets1(2);
    }
}

用synchronized關鍵字保護代碼塊時,咱們使用對象做爲它的傳入參數。JVM保證同一時間只有一個線程可以訪問這個對象保護的代碼保護塊(注意:咱們一直談論的是對象,不是類)。spa

備註:這個例子使用了一個對象來控制對vacanciesCinema1屬性的訪問,因此同一時間只有一個線程可以修改這個屬性; 使用了另外一個對象來控制vacanciesCinema2屬性的訪問,因此同一時間只有一個線程可以修改這個屬性。可是,這個例子容許同時運行兩個線程:一個修改vacancesCinema1屬性,另外一個修改vacanciesCinema2屬性。
線程

相關文章
相關標籤/搜索