線程安全,syncronized 用法

1,爲何有線程安全問題?安全

當多個線程同時共享同一個全局變量或靜態變量,作寫的操做時,可能會發生數據衝突問題,也就是線程安全問題。可是作讀操做是不會發生數據衝突問題。多線程

 

public class TrainThread implements Runnable {

    // 定義初始化票100張
    private int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "賣出了第" + (100 - ticketCount + 1 + "張票"));
            ticketCount--;
        }
    }

}
public class App {
    public static void main(String[] args) throws InterruptedException {
        TrainThread trainThread = new TrainThread();
        
        //模擬了兩個線程,必須都用同一個Runnable 的子類對象,才能叫 實現資源的共享
        Thread thread1 = new Thread(trainThread);
        Thread thread2 = new Thread(trainThread);
        thread1.start();
        thread2.start();
    }

}

可能出現的狀況:同時賣了某一張票函數

Thread-1賣出了第1張票
Thread-1賣出了第2張票
Thread-0賣出了第1張票
Thread-0賣出了第4張票
Thread-1賣出了第3張票
Thread-1賣出了第6張票

 

:爲何使用線程同步或使用鎖能解決線程安全問題呢?this

:將可能會發生數據衝突問題(線程不安全問題),只能讓當前一個線程進行執行。代碼執行完成後釋放鎖,讓後才能讓其餘線程進行執行。這樣的話就能夠解決線程不安全問題。spa

:什麼是多線程之間同步?線程

:當多個線程共享同一個資源,不會受到其餘線程的干擾code

 

2, 實現線程同步,syncronized 的用法對象

解決一:blog

鎖對象資源

syncronized 同步代碼塊:就是將可能會發生線程安全問題的代碼,給包括起來。

synchronized(同一個數據){

 可能會發生線程衝突問題

}

public class TrainThread implements Runnable {

    // 定義初始化票100張
    private int ticketCount = 100;
    //定義了一個共享的對象
   private Object obj = new Object(); public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "賣出了第" + (100 - ticketCount + 1 + "張票"));
                ticketCount--;
            }
        }

    }

}

解決二:

同步函數,

在方法上修飾synchronized 稱爲同步函數

鎖方法

public class TrainThread implements Runnable {

    // 定義初始化票100張
    private int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        sale();
    }

    private synchronized void sale() {
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "賣出了第" + (100 - ticketCount + 1 + "張票"));
            ticketCount--;
        }
    }
}

 

3,同步函數,所方法,實際上是this 鎖

證實,兩個線程,一個線程走同步代碼塊,(鎖住了自定義object對象)的代碼,

另外一個走同步函數,鎖方法的的代碼,結果數據有衝突,證實了syncronized 沒有效,並無鎖住同一資源

將鎖對象的object 換成this,則沒有數據衝突

4,是靜態同步函數?

方法上加上static關鍵字,使用synchronized 關鍵字修飾 或者使用類.class文件。

靜態的同步函數使用的鎖是  該函數所屬字節碼文件對象

仍是加syncronized,和以前沒有區別,鎖方法

public class TrainThread implements Runnable {

    // 定義初始化票100張
    private static int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        sale();
    }

    private  synchronized static void sale() {
        while (ticketCount > 0) {
            System.out.println(Thread.currentThread().getName() + "賣出了第" + (100 - ticketCount + 1 + "張票"));
            ticketCount--;
        }
    }
}

鎖當前類的的字節碼文件的對象,不是this,或者自定義的對象

public class TrainThread implements Runnable {

    // 定義初始化票100張
    private static int ticketCount = 100;

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (TrainThread.class) {
            while (ticketCount > 0) {
                System.out.println(Thread.currentThread().getName() + "賣出了第" + (100 - ticketCount + 1 + "張票"));
                ticketCount--;
            }
        }
    }

}
相關文章
相關標籤/搜索