synchronized同步靜態方法是的使用注意實現

先明確幾點:

1、所有synchronized修飾的非靜態方法用的都是同一把鎖:實例對象本身

2、所有synchronized修飾的靜態方法用的都是同一把鎖:類對象本身

3、而對於同步塊,由於其鎖是可以選擇的,所以只有使用同一把鎖的同步塊之間纔有着競態條件

好了,請看如下代碼

class CsdnMain{
    public static void main(String[] args){
        List<Ipbean> ipbeanList=new ArrayList<>();//假設裏面已經有100個數據了
        for (int i=0;i<3;i++){
            Thread thread=new Thread(new Runnable(){
                @Override
                public void run() {
                    Csdn.filter(ipbeanList);
                }
            });
            thread.start();
        }
    }
}

class Csdn{
    public static List<Ipbean> tenders=new ArrayList<>();
    public static synchronized void add(Ipbean ipbean){
        tenders.add(ipbean);
    }

    public static synchronized void filter(List<Ipbean> ipbeanList) throws InterruptedException {
        if (ipbeanList==null)return;
        for (Ipbean ipbean:ipbeanList){
            if ("http".equals(ipbean.getType().toLowerCase())){
                Thread thread=new Thread(new Runnable(){
                    @Override
                    public void run() {
                        add(ipbean);
                    }
                });
                thread.start();
                thread.join();
            }

        }
    }
}

你覺得這個代碼能夠正常執行完畢嗎?

答案是:不一定

如果列表中的IP都不是走http協議的 那麼這個程序確實會正確執行完畢,但是如果有一個走http協議的 那就會出現死鎖

原因如下:

       當某一個線程在執行filter時,如果滿足執行add的條件,那麼該線程會新建另外一個線程去執行add方法,那麼就出問題了,Csdn這個類對象鎖此時掛在"該線程"上,沒有被釋放,而在其內部創建去執行add方法的線程也需要Csdn這個類對象鎖,一個需要鎖,一個不放鎖,並且不放鎖的又需要要鎖的線程執行完畢才能繼續執行,死鎖就出現了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章