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--; } } } }