1. 程式人生 > >java多線程(線程安全,線程同步)

java多線程(線程安全,線程同步)

sync com art 線程同步 implement color 子類 ace this

一.線程安全

如果有多個線程在同時運行,而這些線程可能會同時運行這段代碼。程序每次運行結果和單線程運行的結果是一樣的,而且其他的變量的值也和預期的是一樣的,就是線程安全的。

通過電影院賣票,演示線程的安全問題:

模擬電影院的賣票過程。本次電影的座位共100個(本場電影只能賣100張票)。模擬電影院的售票窗口,實現多個窗口同時賣這場電影票(多個窗口一起賣這100張票)

需要窗口,采用線程對象來模擬;需要票,Runnable接口子類來模擬

//測試類
public class ThreadDemo {
    public static void main(String[] args) {
        //創建票對象
Ticket ticket = new Ticket(); //創建3個窗口 Thread t1 = new Thread(ticket, "窗口1"); Thread t2 = new Thread(ticket, "窗口2"); Thread t3 = new Thread(ticket, "窗口3"); t1.start(); t2.start(); t3.start(); } }
//模擬票
public class
Ticket implements Runnable { //共100票 int ticket = 100; public void run() { //模擬賣票 while(true){ if (ticket > 0) { //模擬選坐的操作 try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()
+ "正在賣票:" + ticket--); } } }

技術分享圖片

運行結果發現:

①票出現了重復的票

②錯誤的票 0、-1

線程安全問題都是由全局變量及靜態變量引起的。若每個線程中對全局變量、靜態變量只有讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執行寫操作,一般都需要考慮線程同步,否則的話就可能影響線程安全。

二.線程同步(線程安全處理Synchronized)

java中提供了線程同步機制,它能夠解決上述的線程安全問題。

線程同步的方式有兩種:

同步代碼塊

同步方法

1.同步代碼塊

//同步代碼塊: 在代碼塊聲明上 加上synchronized
synchronized (鎖對象) {
    可能會產生線程安全問題的代碼
}

同步代碼塊中的鎖對象可以是任意的對象;但多個線程時,要使用同一個鎖對象才能夠保證線程安全。

//使用同步代碼塊,對電影院賣票案例中Ticket類進行如下代碼修改:
public class Ticket implements Runnable {
    //共100票
    int ticket = 100;
    //定義鎖對象
    Object lock = new Object();
    @Override
    public void run() {
        //模擬賣票
        while(true){
            //同步代碼塊
            synchronized (lock){
                if (ticket > 0) {
                    //模擬電影選坐的操作
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--);
                }
            }
        }
    }
}

2.同步方法

//同步方法:在方法聲明上加上synchronized
public synchronized void method(){
       可能會產生線程安全問題的代碼
}

同步方法中的鎖對象是 this

//使用同步方法,對電影院賣票案例中Ticket類進行如下代碼修改:
public class Ticket implements Runnable {
    //共100票
    int ticket = 100;
    //定義鎖對象
    Object lock = new Object();
    @Override
    public void run() {
        //模擬賣票
        while(true){
            //同步方法
            method();
        }
    }

//同步方法,鎖對象this
    public synchronized void method(){
        if (ticket > 0) {
            //模擬選坐的操作
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在賣票:" + ticket--);
        }
    }
}
//靜態同步方法: 在方法聲明上加上static synchronized
public static synchronized void method(){
可能會產生線程安全問題的代碼
}

靜態同步方法中的鎖對象是 類名.class

java多線程(線程安全,線程同步)