java中使用synchronized進行修飾鎖定的必須是公用的資源,否則還是存在併發問題

在java中,原來以爲用synchronized修飾的方法在任何情況下應該都是單併發執行的,後來經過測試表明這個方法必須是公用的,因爲synchronized鎖定的對象而不是對象的方法,所以如果這個對象不是公用的,那麼即使加了synchronized方法也是沒有用的。

1.這裏有一個類,它負責創建100個線程並啓動他們

/*
 * ©2002-2016 ****, Inc. All rights reserved.
 */

package com.test.thread;

/**
 * Starts 功能描述:創建並啓動100個線程
 *
 * @author RickyLee
 * @date 2016/11/4 13:52
 */
public class Starts {
    public static void main(String[] args) {
        for(int i=0;i<100;i++){
            String name="[thread"+i+"]";
            new TT(name).start();
        }
    }
}

2.每個線程每隔0.1秒執行一次打印操作,一直打印100次

/*
 * ©2002-2016 ****, Inc. All rights reserved.
 */

package com.test.thread;

/**
 * Thread 功能描述:TODO
 *
 * @author RickyLee
 * @date 2016/11/4 13:41
 */
public class TT extends Thread{
    private String tName=null;
    public TT(String name){
        tName=name;
    }
    public void run() {
        try {
            for(int i=0;i<100;i++){
                Test.start(tName);
                sleep(100);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3.調用公用打印方法

/*
 * ©2002-2016 ****, Inc. All rights reserved.
 */

package com.test.thread;

/**
 * Test 功能描述:負責方法在執行的時候給全局變量+1並打印全局變量
 *
 * @author RickyLee
 * @date 2016/11/4 13:41
 */
public class Test {
    private static int counter=0;
    public synchronized static void start(String threadName){
        counter++;
        System.out.println(threadName+"    "+counter);
    }
}


請注意上面的這個start方法是一個靜態方法,以保證各個線程使用的是同一個對象,因爲synchronized修飾的方法只是鎖定了這個對象,如果是new的對象用這個修飾它是鎖不住其它對象的,它只能鎖住他自己,所以此處用了static修飾,以保證對象唯一。運行Starts方法,得到如下結果:


大家可以試一下,如果把static去掉,前面採用new Test().start(tName);的方式,結果就會非常錯亂。


以前的認識有些誤區,一起共勉!


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