synchronized的用法與注意事項
阿新 • • 發佈:2019-01-27
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的多執行緒使用關鍵是看哪個作為鎖物件,如果鎖的不是同一個物件,那麼就無法達到同步的目的。