線程安全

1. 什麼叫線程安全?java

    多線程對共享資源進行的操做,受到其餘線程的干擾,致使數據偶問題,這種現象叫作線程安全問題。安全

package com.cn.test.thread;

public class TrainThread implements Runnable {

    /**
     * 兩個線程進行售票100張
     */
    private  int trainTicket = 100;
    @Override
    public void run() {
        
        while (trainTicket > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 進行售票
            System.out.println(Thread.currentThread().getName() + "開始售票:" + (100 - trainTicket + 1) + "張");
            trainTicket--;
        }
    }

    public static void main(String[] args) {
        TrainThread train = new TrainThread();
        Thread  t1 = new Thread(train,"窗口1");
        Thread  t2 = new Thread(train,"窗口2");
        t1.start();
        t2.start();
    }
}

運行結果:多線程

窗口1開始售票:1張
窗口2開始售票:1張
窗口1開始售票:3張
窗口2開始售票:3張
窗口1開始售票:5張
窗口2開始售票:5張
窗口1開始售票:7張
窗口2開始售票:7張
窗口2開始售票:9張
窗口1開始售票:9張
窗口2開始售票:11張
窗口1開始售票:12張
窗口2開始售票:13張
窗口1開始售票:14張
窗口2開始售票:15張
窗口1開始售票:16張
窗口2開始售票:17張
窗口1開始售票:18張
窗口2開始售票:19張
窗口1開始售票:20張
窗口2開始售票:21張
窗口1開始售票:22張
窗口2開始售票:23張
窗口1開始售票:24張
窗口2開始售票:25張
窗口1開始售票:26張
窗口2開始售票:27張
窗口1開始售票:28張
窗口2開始售票:29張
窗口1開始售票:30張
窗口2開始售票:31張
窗口1開始售票:32張
窗口2開始售票:33張
窗口1開始售票:34張
窗口2開始售票:35張
窗口1開始售票:36張
窗口2開始售票:37張
窗口1開始售票:38張
窗口2開始售票:39張
窗口1開始售票:40張
窗口2開始售票:41張
窗口1開始售票:42張
窗口2開始售票:43張
窗口1開始售票:44張
窗口2開始售票:45張
窗口1開始售票:46張
窗口2開始售票:47張
窗口1開始售票:48張
窗口2開始售票:49張
窗口1開始售票:50張
窗口2開始售票:51張
窗口1開始售票:52張
窗口2開始售票:53張
窗口1開始售票:54張
窗口2開始售票:55張
窗口1開始售票:56張
窗口2開始售票:57張
窗口1開始售票:58張
窗口2開始售票:59張
窗口1開始售票:60張
窗口2開始售票:61張
窗口1開始售票:62張
窗口2開始售票:63張
窗口1開始售票:64張
窗口2開始售票:65張
窗口1開始售票:66張
窗口2開始售票:67張
窗口1開始售票:68張
窗口2開始售票:69張
窗口1開始售票:70張
窗口2開始售票:71張
窗口1開始售票:72張
窗口2開始售票:73張
窗口1開始售票:74張
窗口2開始售票:75張
窗口1開始售票:76張
窗口2開始售票:77張
窗口1開始售票:78張
窗口2開始售票:79張
窗口1開始售票:80張
窗口2開始售票:81張
窗口1開始售票:82張
窗口2開始售票:83張
窗口1開始售票:84張
窗口2開始售票:85張
窗口1開始售票:86張
窗口2開始售票:87張
窗口1開始售票:88張
窗口2開始售票:89張
窗口1開始售票:90張
窗口2開始售票:91張
窗口1開始售票:92張
窗口2開始售票:93張
窗口1開始售票:94張
窗口2開始售票:95張
窗口1開始售票:96張
窗口2開始售票:97張
窗口1開始售票:98張
窗口2開始售票:99張
窗口1開始售票:100張
窗口2開始售票:101張

線程安全解決的辦法:併發

        使用多線程之間同步synchronized或使用鎖(lock)。ide

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

       將可能發生線程安全的代碼,在同一時刻只有一個線程對此進行操做,代碼執行完畢以後釋放鎖以後才讓其餘線程併發執行,這樣就會解決線程安全的問題。spa

什麼是線程同步?線程

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

解決辦法1:對象

       同步代碼塊。 將可能發生線程安全的代碼用同步代碼塊包裹起來。

              synchronized(同一個數據) {

                   可能會發生線程衝突問題

                }

        同步代碼塊須要傳遞的對象(鎖對象):就是鎖住這個對象,表示這個對象正在爲我服務,其餘人不能用(非synchronized代碼塊、方法除外)。

 

		
		while (trainTicket > 0) {
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized (obj) {
				// 進行售票
				if (trainTicket > 0) {
					System.out.println(Thread.currentThread().getName() + "開始售票:" + (100 - trainTicket + 1) + "張");
					trainTicket--;
				}
			}
		}
	

  解決辦法2:

           同步函數,在發生線程安全的函數中加入sychnorized關鍵字。

  靜態同步函數:

     方法上加上static關鍵字,使用synchronized 關鍵字修飾 或者使用類.class文件。靜態的同步函數使用的鎖是  該函數所屬字節碼文件對象能夠用 getClass方法獲取,也能夠用當前  類名.class 表示。

死鎖:

 

同步中嵌套同步,致使鎖沒法釋放

 

 

package com.cn.test.thread;

public class TestDeadThread implements Runnable {

    
    
    private boolean flag = true;
    private static int trainCount = 100;
    private Object mutex = new Object();

    @Override
    public void run() {
        if (flag) {
            while(true) {
                synchronized (mutex) {
                     sale();
                }
            }
        } else {
            while (true) {
                sale();
            }

        }

    }

    private synchronized void sale() {
        synchronized (mutex) {
            if (trainCount > 0) {
                try {
                    Thread.sleep(40);
                } catch (Exception e) {

                }
                System.out.println(Thread.currentThread().getName() + ",出售 第" + (100 - trainCount + 1) + "張票.");
                trainCount--;
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        TestDeadThread  test1 = new TestDeadThread();
        Thread t1 = new Thread(test1,"thread-1");
        Thread t2 = new Thread(test1,"thread-2");
        t1.start();
        Thread.sleep(40);
        test1.flag  = false;
        t2.start();


    }

}

 

運行結果:

thread-1,出售 第1張票.
thread-1,出售 第2張票.
thread-1,出售 第3張票.
thread-1,出售 第4張票.
thread-1,出售 第5張票.
thread-1,出售 第6張票.
thread-1,出售 第7張票.
thread-1,出售 第8張票.
thread-1,出售 第9張票.
thread-1,出售 第10張票.
thread-1,出售 第11張票.
thread-1,出售 第12張票.
thread-1,出售 第13張票.
thread-1,出售 第14張票.
thread-1,出售 第15張票.
thread-1,出售 第16張票.
thread-1,出售 第17張票.
thread-1,出售 第18張票.
thread-1,出售 第19張票.
thread-1,出售 第20張票.
thread-1,出售 第21張票.
thread-1,出售 第22張票.
thread-1,出售 第23張票.
thread-1,出售 第24張票.
thread-1,出售 第25張票.
相關文章
相關標籤/搜索