JavaにおけるSynchronizedの使用上の注意事項

1841 ワード

回転:http://www.blogjava.net/freeman1984/archive/2011/10/17/361403.html Java 1.5の前に、synchronizedは最もよく使われているjavaサポート合併手段であるべきです.じゃ、synchronizedはどうやってできますか?java 1.0からjavaの中の各オブジェクトは一つの内部錠です.一つの種類の方法がsynchronizedキーワードによって修飾されると、このオブジェクトのロックは全体の方法を保護します.例えば:
public synchronized void method(){

    method body

}
に等しい
public void method(){

    this.intrinsicLock.lock();

    try{

        method body;

    }finally(){

        this.intrinsicLock.unlock();

    }

}
上のコード例から、synchronizedの使用は比較的簡単であることが分かります.これは多くの初心者がJavaプログラミングに遭遇した時に落とし穴に落ちてしまい、synhronizedがすべてを解決できるなら、たとえ3721であろうと、合併の可能性があるところであれば、synchronizedのキーワードを加えるのは明らかに間違っています.javaオブジェクトでは、このjavaオブジェクトはこの一つの内部錠だけであり、そのうちの一つのsynchronized方法はこのロックを取得し、もう一つのsynchronizedメソッドの呼び出しはブロックされます.すなわち
class sync{

    public synchronized void methodA(){};

    public synchronized void methodB(){};

    ... ...

}
methodAとmethodBは最初から互いに反発しあっています.methodAとmethodBが入って待ち合うと、デッドロックが発生しやすくなります.もしこのような状況に遭遇したら、どうすればいいですか?一般的な方法は、方法の内部に意味のないオブジェクトを新規作成し、この無意味なオブジェクトに同期ロックをかけることです.
public class Sync {  
    private int i;  
      
    public void plus(){  
        Object dummy = new Object();  
        synchronized(dummy){  
            i++;  
        }  
    }  
      
    public void minus(){  
        Object dummy = new Object();  
        synchronized(dummy){  
            i--;  
        }         
    }  
}  
 
なお、静的系をsynchronizedとして宣言する方法も合法的である.例えば、Syncにstatic synchronized方法があるなら、この方法が呼び出された時、Sync.classという種類のオブジェクト自体はjvmにロックされます.