Javaでの同期コードブロック、同期メソッド、同期ロック

1818 ワード

マルチスレッドで問題が発生しやすい理由
複数の文が同じスレッドを操作してデータを共有する場合、1つのスレッドは複数の文に対して一部しか実行されず、まだ実行が完了しておらず、別のスレッドが実行に参加します.共有データのエラーが発生しました.すなわち、複数のスレッドが実行する不確実性は、実行結果の不安定性を引き起こす.
例:
  • 複数のスレッドによる帳簿の共有は、操作の不完全性をもたらし、データを破壊する.
  • 駅で切符を販売し、複数の窓口で同時に切符を販売する.

  • 解決策
    同期コードブロック
    synchronized(obj)
    {
        //         
    }

    ここでobjは、同期モニタ、すなわちロックと呼ばれ、スレッドが同期コードブロックを実行し始める前に、同期コードブロックに対するロックを取得しなければならないという原理がある.また、同期モニタのロックは、いつでも1つのスレッドしか取得できません.同期コードブロックの実行が完了すると、スレッドは同期モニタのロックを解放します.
    ここでのロックは、非静的メソッドではthisであり、静的メソッドでは現在のクラス自体(例えば、単一のモードの怠け者式:Singleton.class)である.
    //      -    
    class Singleton {
    	private Singleton() {
    	}
    
    	private static Singleton s = null;
    
    	private static Singleton getInstance() {
    		if (s == null) {
    			synchronized (Singleton.class) {
    				if (s == null) {
    					s = new Singleton();
    				}
    			}
    		}
    		return s;
    	}
    }

    同期メソッド
    public synchronized void testThread()
    {
        //         
    }

    キーワードsynchronized修飾のメソッドでは、同期モニタを指定する必要はありません.この同期メソッド(staticメソッドではありません)は、同期モニタを明示的に指定する必要はありません.同期メソッドの同期モニタはthis、つまりメソッドを呼び出すオブジェクトです.
    synchronizedは、メソッドを修飾したり、コードブロックを修飾したりすることができますが、コンストラクタ、メンバー変数などを修飾することはできません.
    シンクロロック
    class A
    {
        private final ReentrantLock lock=new ReentrantLock();
        public void method()
        {
            lock.lock();
            try{
                    //         
                }catch(Exception e){
                    e.printStackTrace();
                }finally{
                    lock.unlock();
            }
        }
    }

    これは、同期ロックオブジェクトを明示的に定義することによって同期を実現するより強力なスレッド同期メカニズムであり、ここでの同期ロックはロックオブジェクトによって機能する.ロックを使用するのは同期コードブロックを使用するのと少し似ていますが、ロックを使用するとロックオブジェクトとして表示され、同期メソッドを使用するとシステムは現在のオブジェクトを同期モニタとして暗黙的に使用します.
    ここで,必要に応じてロックを解放できることを確保するために,コードにはfinallyを用いてロックの解放を確保し,デッドロックを防止する.