黑馬程序員_Java基礎[26]_線程2、同步代碼塊、同步函數

---------- android培訓 java培訓 、期待與您交流! ----------

【同步代碼塊】


 * *在【a】手動添加休眠10毫秒,
 *通過分析發現 打印出了0   -1   -2  等錯票
 *多線程的運行出現了安全無問題。

 *問題的原因:
 *        當多條語句在操作同一個線程共享數據時,一個線程對多個語句只執行流量一部分,
 *        還沒有執行完,另一個線程參與進來執行,導致共享數據的錯誤
 *
 *解決辦法就是,
 *        對多條操作共享數據的語句,只能讓一個線程都執行完,在執行過程中,其他現在不可以參與執行
 *
 *java對多線程的安全問題,提供了專業的解決方式
 *
 *就是【同步代碼塊】:
 *
 *sychronized(對象){
 *    需要被同步的代碼
 *}
 *
 *對象如同鎖,持有鎖的線程可以在同步中執行。
 *沒有持有鎖的線程即使獲取到cpu的執行權,也進不去,因爲沒有獲取鎖。

 *
 *火車上的衛生間- - 經典解釋鎖的例子。
 *
 *
 *同步的【前提】:
 *1、必須要有2個或者2個以上的線程
 *2、必須是多個線程使用同一個鎖
 *
 *必須保證同步中只能一個線程在運行
 *
 *【好處】:解決了多線程的安全問題
 *
 *【弊端】:多個線程都需要判斷鎖,較爲消耗資源。

 */


class Ticket1 implements Runnable{//方式二
    private int tick=100;
    Object obj=new Object();
    public void run(){
        while(true){
            synchronized(obj){//obj 就相當於鎖。
                if(tick>0){
                    try{
                        Thread.sleep(10);//【a】
                    }
                    catch(Exception e){}
                    System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
                }
            }
            
    
        }
    }
}    



public class D_Th_test3 {

    public static void main(String[] args) {

        Ticket t=new Ticket();//這只是創建對象
        
        Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        Thread t3=new Thread(t);
        t1.start();
        t2.start();
        t3.start();

        /*把Runnable 子類對象當作參數傳遞給Thread方法的構造函數,
         * 通過調用Thread類的start方法開啓線程並調用Runnable中的run方法

         */
        
    }

}

-----------------------------------------------------------------------------------------------------------

/*sychronized  練習
 * 需求:
 * 銀行有一個金庫
 * 有兩個儲戶,分別存300,每次100 存3次。
 *
 * 目的:該程序是否有安全問題,如果有,如何解決。】
 *
 * 如何找到問題
 * 1、明確那些代碼是多線程代碼
 * 2、明確共享數據
 * 3、明確多線程中那些語句是操作共享數據的

 *
 * 【同步有2種表現形式】:
 * 1、同步代碼塊   synchronized(對象){}
 * 2、同步函數[b]

 *
 * 下列:【test2】
 * 返回去看剛剛test2賣票的小案例,他能使用同步函數嗎,
 * 答案是否定的,因爲while是不需要同步的,鎖到一起後,會出現一直循環打印的現象。
 * 我們知道 synchronized中的鎖是對象的,下來中的對象是誰?我們知道,show()前面減省了this,應該是 this.show();
 * 那麼這個鎖就是this的。【明天繼續,實在是困了。】
 *
 * 同步函數,到底用的是那一個鎖
 * 【非靜態同步函數用的鎖,是this】
 *
 * 通過該程序來賣票
 * 使用兩個線程來賣票
 * 一個線程在同步代碼塊中,
 * 一個線程在同步函數中,
 * 都在執行賣票動作。
 *
 * 下列代碼運行觀察,有一定機率打印出0號票,
 * 我們把run方法中傳入的obj鎖改爲this,我們在試試
 * 更改後,多次運行均無0出現
 *
 * 所以,推理得出同步函數使用的鎖是this
 *
 *
 *
 */


//[b]  同步函數
class Ticket4 implements Runnable{//方式二
    private int tick=100;
    Object obj=new Object();
    boolean flag=true;
    public void run(){
        if(flag){
            while(true){
                //synchronized(obj){//obj 就相當於鎖。
                synchronized(this){//更換爲this
                    if(tick>0){
                        try{
                            Thread.sleep(10);//【a】
                        }
                        catch(Exception e){}
                        System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
                    }
                }
            }
        }
        else{
            while(true)
            show();
        }
    }
    
    public synchronized void show(){
            if(tick>0){
                try{
                    Thread.sleep(10);//【a】
                }
                catch(Exception e){}
                System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
            }
    }
}    
 
public class D_Th_test5 {
    public static void main(String[] args) {
        Ticket4 t=new Ticket4();
        Thread t1=new Thread(t);
        Thread t2=new Thread(t);
        t1.start();
        try{
            Thread.sleep(10);//【a】
        }
        catch(Exception e){}
        t.flag=false;
        t2.start();


    }

}



---------- android培訓、 java培訓 、期待與您交流!----------
黑馬官網: http://edu.csdn.net/heima
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章