Java_線程同步--synchronized

1、線程的同步

在多線程程序中,它們多個線程之間是共享一塊內存的。java

當某個線程正在讀取該內存塊的信息時,並在修改內存信息的同時,並在此發生意外,如:阻塞,若是有別的線程也進來訪問這塊內存,而且也要修改該內存塊的信息,這是就會發生意想不到的錯誤。編程

好比:你有一個銀行帳戶,帳戶裏面有2000塊錢。多線程

一天,你拿着銀行本子去銀行取錢,打算取1500,而後銀行的工做人員就會經過電腦程序檢查你的帳戶中是否有超過1500的錢,查詢以後,證實你的帳戶有超過1500,能夠取款,而後響應取款的程序!固然,你取款程序執行完以後,纔會從你的帳戶減去1500,然而就在執行取款程序的同時,也就是還沒從你的帳戶裏減去1500;巧的是,這時你的老媽/老爸拿着你的銀行卡也在l另外一處的取款機上取錢,取款機同時也會去檢查你的帳戶裏的錢有沒有超過1500,這時固然超過1500,而後你老媽取錢成功啦,你也取錢成功,而後大家家取了3000塊,卡里還剩500,這種好事多好啊。ide

。。。。。學習

固然,這種事情是不會發生的,哈哈!!spa

要解決上面這個問題,咱們就得了解程序的原子性這個概念。線程

程序的原子性:

也就是說保證一個程序或者某個代碼塊完整執行的性質,在這個過程中,別的線程若是想執行該代碼塊時是沒有權限的。code

還有若是在執行過程,忽然中斷該程序,程序的內存信息是不會修改的。對象

synchronzied 關鍵字:

對象鎖。有了對象鎖,就保證了在一個線程執行某個代碼塊的時候,別的線程就不訪問到該代碼塊了,就避免了像上面那樣形成數據混亂了。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中很重要的知識點,涉及不少編程的概念,好比還有死鎖問題,線程池什麼的。

請繼續關注。。。。

若是您認爲哪裏有什麼問題歡迎一塊兒學習,溝通解決!!

相關文章
相關標籤/搜索