1. 程式人生 > >synchronized的用法與注意事項

synchronized的用法與注意事項

synchronized關鍵字在java多執行緒程式設計過程中非常的有用,不過在程式設計過程中由於對synchronized的理解不足,也會有很多坑。
synchronized(object)是最常用的方法,它可以鎖住需要訪問的程式碼塊,使只有一個執行緒訪問而達到同步的目的。例如如下程式碼:

public class MulThreadTest {
    public static int a = 0;
    public  void addInt1(){
        synchronized(this){
            a++;
            System.out.println(a);
        }
    }
    public
static void main(String[] args){ final MulThreadTest test = new MulThreadTest(); for(int i=0;i<3;i++){ new Thread(new Runnable() { @Override public void run() { for(int j=0;j<100;j++) test.addInt1(); } }).start(); } } }

執行上述程式碼沒有問題,synchronized使用this做鎖物件,即使用的是引用的物件test做鎖物件。因為synchronized包含的程式碼塊包含了方法區裡的所有程式碼,所以方法addInt1()等同如下形式:

    public synchronized void addInt2(){
        a++;
        System.out.println(a);
    }

如果main函式的方法將final物件test放入多執行緒中,如下:

    public static void main(String[] args) throws InterruptedException {
        for
(int i=0;i<3;i++){ new Thread(new Runnable() { @Override public void run() { MulThreadTest test = new MulThreadTest(); for(int j=0;j<100;j++) test.addInt1(); } }).start(); } }

此時,執行程式碼會發現結果不是我們想要的。因為此時執行的每一個執行緒都有一個鎖物件test,他們之間沒有做到互斥訪問,此時我們就需要更改addInt1()方法如下:

    public void addInt3(){
        synchronized (MulThreadTest.class) {
            a++;
            System.out.println(a);
        }
    }

將鎖加在類上或者宣告一個靜態物件做為鎖物件 :
static Object object = new Object();

總結:
synchronized的多執行緒使用關鍵是看哪個作為鎖物件,如果鎖的不是同一個物件,那麼就無法達到同步的目的。