在多線程程序中,它們多個線程之間是共享一塊內存的。java
當某個線程正在讀取該內存塊的信息時,並在修改內存信息的同時,並在此發生意外,如:阻塞,若是有別的線程也進來訪問這塊內存,而且也要修改該內存塊的信息,這是就會發生意想不到的錯誤。編程
好比:你有一個銀行帳戶,帳戶裏面有2000塊錢。多線程
一天,你拿着銀行本子去銀行取錢,打算取1500,而後銀行的工做人員就會經過電腦程序檢查你的帳戶中是否有超過1500的錢,查詢以後,證實你的帳戶有超過1500,能夠取款,而後響應取款的程序!固然,你取款程序執行完以後,纔會從你的帳戶減去1500,然而就在執行取款程序的同時,也就是還沒從你的帳戶裏減去1500;巧的是,這時你的老媽/老爸拿着你的銀行卡也在l另外一處的取款機上取錢,取款機同時也會去檢查你的帳戶裏的錢有沒有超過1500,這時固然超過1500,而後你老媽取錢成功啦,你也取錢成功,而後大家家取了3000塊,卡里還剩500,這種好事多好啊。ide
。。。。。學習
固然,這種事情是不會發生的,哈哈!!spa
要解決上面這個問題,咱們就得了解程序的原子性這個概念。線程
也就是說保證一個程序或者某個代碼塊完整執行的性質,在這個過程中,別的線程若是想執行該代碼塊時是沒有權限的。code
還有若是在執行過程,忽然中斷該程序,程序的內存信息是不會修改的。對象
對象鎖。有了對象鎖,就保證了在一個線程執行某個代碼塊的時候,別的線程就不訪問到該代碼塊了,就避免了像上面那樣形成數據混亂了。blog
以下模仿一個多窗口售票的程序:
沒有關鍵字synchronize以前:
1 package com.thread.Synchronized; 2 3 /** 4 * 線程同步 5 * --》synchronized關鍵字 6 * 7 * 模擬一個多窗口售票的例子 8 * 9 * @author hunjun 10 */ 11 public class TestSync implements Runnable{ 12 private static int ticketNum = 200; 13 14 public static void main(String[] args) { 15 TestSync ts1 = new TestSync(); 16 TestSync ts2 = new TestSync(); 17 TestSync ts3 = new TestSync(); 18 19 Thread t1 = new Thread(ts1,"窗口一"); 20 Thread t2 = new Thread(ts2,"窗口二"); 21 Thread t3 = new Thread(ts3,"窗口三"); 22 23 t1.start(); 24 t2.start(); 25 t3.start(); 26 } 27 28 @Override 29 public void run() { 30 // TODO Auto-generated method stub 31 try { 32 while(ticketNum > 0){ 33 Thread.sleep(2000); 34 TestSync.saleTicket(); 35 } 36 } catch (InterruptedException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 42 public static void saleTicket(){ 43 if(ticketNum > 0){ 44 //開始售票 45 System.out.println(Thread.currentThread().getName()+"售出第 "+ticketNum+" 張票。。"); 46 ticketNum --; 47 } 48 } 49 50 }
結果;
窗口一售出第 200 張票。。
窗口二售出第 200 張票。。
窗口三售出第 200 張票。。
窗口一售出第 197 張票。。
窗口三售出第 197 張票。。
窗口二售出第 197 張票。。
數據很混亂。。。由於在當前線程sleep的時候別先進來來,改變數據,就會出現混亂。
加了關鍵字synchronize以後
package com.thread.Synchronized; /** * 線程同步 * --》synchronized關鍵字 * * 模擬一個多窗口售票的例子 * * @author hunjun */ public class TestSync implements Runnable{ private static int ticketNum = 200; public static void main(String[] args) { TestSync ts1 = new TestSync(); TestSync ts2 = new TestSync(); TestSync ts3 = new TestSync(); Thread t1 = new Thread(ts1,"窗口一"); Thread t2 = new Thread(ts2,"窗口二"); Thread t3 = new Thread(ts3,"窗口三"); t1.start(); t2.start(); t3.start(); } @Override public void run() { // TODO Auto-generated method stub try { while(ticketNum > 0){ Thread.sleep(2000); TestSync.saleTicket(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
/*在這裏加了關鍵字synchronized*/ public static synchronized void saleTicket(){ if(ticketNum > 0){ //開始售票 System.out.println(Thread.currentThread().getName()+"售出第 "+ticketNum+" 張票。。"); ticketNum --; } } }
結果:
窗口三售出第 200 張票。。
窗口二售出第 199 張票。。
窗口一售出第 198 張票。。
窗口一售出第 197 張票。。
窗口二售出第 196 張票。。
窗口三售出第 195 張票。。
窗口一售出第 194 張票。。
窗口二售出第 193 張票。。
窗口三售出第 192 張票。。
總結:多線程是java中很重要的知識點,涉及不少編程的概念,好比還有死鎖問題,線程池什麼的。
請繼續關注。。。。
若是您認爲哪裏有什麼問題歡迎一塊兒學習,溝通解決!!