synchronized 同步方法/塊

同步塊對象同步方法能更細粒度的鎖定內容java

 

同步鎖:太大,容易形成效率低下,過小,鎖不住web

線程安全synchronized   儘量鎖定合理的範圍(不是鎖代碼,而是鎖數據)安全

雙重檢測併發

package com.wxh.syn;
//線程安全synchronized   儘量鎖定合理的範圍(不是鎖代碼,而是鎖數據)
public class Web12306 implements Runnable {
    int numberKey = 10;
    boolean flag = true;
    public static void main(String[] args) {
        Web12306 web = new Web12306();
        new Thread(web,"馬超").start();
        new Thread(web,"關羽").start();
        new Thread(web,"曹操").start();
    }
    public void run() {
             test7();
    }
    //儘量鎖定合理範圍,最合理的方法,雙重檢測
        private void test7() {    
            while(flag) {
                if(numberKey <= 0) {    //判斷還有沒有票
                    flag = false;
                    return;
                }
                synchronized(this) {    //由於對象爲flag 和numberkey,鎖住一個對象是不安全的,
                if(numberKey <= 0) {        //判斷臨界值,如當只有最後一張票時
                    flag = false;
                    return;
                }
                
                
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"-->"+numberKey--);
                }     
            
            }
                }
    
        private void test5() {
            
            
            while(flag) {
                synchronized(this) {    // a,b,c 三個線程,a拿到鎖,進行判斷,釋放鎖,B拿到鎖,釋放鎖,a此時在sleep,B也進入sleep,
                                            //但sleep結束,cpu調度可能先執行B,此時就會出現票數同時拿到
            if(numberKey <= 0) {
                flag = false;
                return;
            }
                }
                
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->"+numberKey--);
                
            
        }
        
            }
        private synchronized void test3() {
            while(true) {
            
            if(numberKey <= 0) {
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->"+numberKey--);
            
        }
        
            
    }
        private  void test2() {
            
            while(flag) {
                synchronized((Integer)numberKey) {    //由於對象爲flag 和numberkey,鎖住一個對象是不安全的,
                if(numberKey <= 0) {
                    flag = false;
                    return;
                }
                
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"-->"+numberKey--);
                }    
            
            }
                }
    
        private  void test() {
            
            while(true) {
                synchronized(this) {    //線程安全,由於this對象包括了numberkey和flag
            if(numberKey <= 0) {
                return;
            }
                
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"-->"+numberKey--);
                }
            
        }
        
            }
        }

            銀行取錢,鎖定銀行帳號:app

package com.wxh.syn;

/**
 * synchronized 鎖執行完畢以後,才釋放鎖
 * 由於銀河存款100,可悲啊取走80後,剩餘20不達到happy的他取錢90要求,return
 * @author Administrator
 *    代碼塊:更加精細控制
 */
public class UnsafeTest {
    public static void main(String[] args) {
         Account1 account = new Account1(170, "結婚禮金");
         Drawing1 you = new Drawing1(account, 80, "可悲啊");
         Drawing1 wif = new Drawing1(account, 90, "happy的他");
         you.start();
         wif.start();
        
    }
}

//建立銀行帳戶
class Account1{
    int money;
    String name;
    public Account1(int money, String name) {
        
        this.money = money;
        this.name = name;
    }
    
}

    //模擬取款
class Drawing1 extends Thread{
    Account1 account;    //取錢的帳戶
    int Outmoney;        //取得錢數
    int pagemoney;        //取得總數
    
    
    public Drawing1(Account1 account, int outmoney,String name) {
        super(name);
        this.account = account;
        Outmoney = outmoney;
    }


    public void run() {
        test();
    }

    //目標鎖定不對,應該鎖定對象(銀行帳號account)
    private  void test() {
        if(account.money <= 0) {    //提升性能的細節,由於每次線程進來都須要判斷鎖是否執行完以後再判斷
            return;                            //而這一步提早判斷當銀行餘額爲0時,不須要執行如下代碼,大大提升了併發量。
        }
        
        synchronized(account) {
        if(account.money -Outmoney <0) {
            return;
        }
        
        
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }
        account.money -= Outmoney;        //帳戶餘額
        pagemoney =  Outmoney;
        
        System.out.println(this.getName()+"--->帳戶餘額"+account.money);
        System.out.println(this.getName()+"--->口袋金額"+pagemoney);
        }                //synchronized 鎖執行完畢以後,才釋放鎖
        
    }
}
相關文章
相關標籤/搜索