synchronizedはいったい何をロックしましたか?


synchronizedキーワードは、マルチスレッドコードを作成するjava開発者がよく使うキーワードであり、その主な役割は方法を同期させることであり、本論文は一連のテストを通して、このキーワードを深く理解することができることを望んでいる。
一.synchronizedの使い方。
始める前に、まずsynchronizedフィールドの使い方を調べます。
1.synchronizedは、メンバー方法を宣言するために使用できます。

public synchronized int method () {

}
2.synchronizedはコードブロック、例えば

public void method {
    synchronized(this) {
        dosth();
    }
}
注、括弧の中には必ず一例があります。
二.synchronizedの役割
以下は具体的なテストを開始します。今回の主なテストはSynchronizedを声明方法に用いる時の主な役割です。以下のTestBean.javaはユーザーテストの主体類です。テストはこのような段階をめぐって行われます。

package org.sluggard.bolg.synctest;

/**
 *          ,     2        ,
 * 2        ,1          1         ,     A   ,
 *       sleep10 ,  B  ,  sleep1 ,         , sleep5 .
 * @author Frank
 *
 */
public class TestBean {
	
	private String dynamicField;
	
	private static String staticField;
	
	/**
	 *        A
	 * @param value
	 */
	public synchronized void dynamicSyncMethodA(String value) {
		System.out.println("I'm synchronized methodA");
		SleepUtil.sleep(10);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 *        B
	 */
	public synchronized void dynamicSyncMethodB(String value) {
		System.out.println("I'm synchronized methodB");
		SleepUtil.sleep(1);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 *       A
	 */
	public static synchronized void staticSyncMethodA(String value) {
		System.out.println("I'm static synchronized methodA");
		SleepUtil.sleep(10);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
	/**
	 *       B
	 */
	public static synchronized void staticSyncMethodB(String value) {
		System.out.println("I'm static synchronized methodB");
		SleepUtil.sleep(1);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
	/**
	 *        
	 */
	public void dynamicUnsyncMethod(String value) {
		System.out.println("I'm dynamic unsynchronized method");
		SleepUtil.sleep(5);
		dynamicField = value;
		System.out.println("Now field is : " + dynamicField);
	}
	
	/**
	 *        
	 */
	public static void staticUnsyncMethod(String value) {
		System.out.println("I'm static unsynchronized method");
		SleepUtil.sleep(5);
		staticField = value;
		System.out.println("Now field is : " + staticField);
	}
	
}

abstract class SleepUtil {
	public static void sleep(int i){
		try {
			Thread.sleep(i*1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
以下はこのようなテストコードの作成について、一連の問題を解決します。
1,synchronized会は全体の種類に居住しますか?
Test.javaは、動的方法Aと動的方法Bのために2つのスレッドクラスを作成し、それぞれ2つのインスタンスを実行するsynchronized方法を作成した。

package org.sluggard.bolg.synctest;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		TestBean testBean1 = new TestBean();
		TestBean testBean2 = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean1);
		ThreadDSB dsb = new ThreadDSB(testBean2);
		dsa.start();
		SleepUtil.sleep(1);
		dsb.start();
	}

}

class ThreadDSA extends Thread{

	@Override
	public void run() {
		testBean.dynamicSyncMethodA("DSA");
	}
	
	private TestBean testBean;

	public ThreadDSA(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}

class ThreadDSB extends Thread{

	@Override
	public void run() {
		testBean.dynamicSyncMethodB("DSB");
	}
	
	private TestBean testBean;
	
	public ThreadDSB(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}
実行結果は以下の通りです
参照
I'm synchronized methodA
I'm synchronized methodB
Now field is:DSB
Now field is:DSA
それから、私たちはメーンメソッドを修正して、次のようにします。
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadDSB dsb = new ThreadDSB(testBean);
		dsa.start();
		SleepUtil.sleep(1);
		dsb.start();
	}
実行結果は以下の通りです
参照
I'm synchronized methodA
Now field is:DSA
I'm synchronized methodB
Now field is:DSB
synchronizedはクラス全体をロックしていないが、ある実例だけをロックしています。異なる例の動的同期方法は同期しません。
2.プログラムがsynchronizedメソッドに入ったら、非同期方法は実行できますか?
Test.javaに非同期方法のスレッドを追加します。
class ThreadDUS extends Thread{

	@Override
	public void run() {
		testBean.dynamicUnsyncMethod("DUS");
	}
	
	private TestBean testBean;
	
	public ThreadDUS(TestBean testBean) {
		super();
		this.testBean = testBean;
	}
}
メールの方法を修正します。
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadDUS dus = new ThreadDUS(testBean);
		dsa.start();
		SleepUtil.sleep(1);
		dus.start();
	}
実行結果は以下の通りです
参照
I'm synchronized methodA
I'm dynamic unsynchronized method
Now field is:DUS
Now field is:DSA
同期ロックは、非同期の方法ではないが、2つの方法を順番に実行したいなら、彼らのすべての束縛を必要とします。
3.synchronizedは動的方法と静的方法を同時にロックしますか?
まず、まずTestBeanを修正して、ダイナミックな方法に静的なメンバー変数の操作を加えます。
public synchronized void dynamicSyncMethodA(String value) {
		System.out.println("I'm synchronized methodA");
		SleepUtil.sleep(10);
		dynamicField = value;
		staticField = value;
		System.out.println("Now dynamicfield is : " + dynamicField + "
Now staticfield is : " + value); }
同様に、静的同期法のためにスレッドクラスに参加し、
class ThreadSSA extends Thread{

	@Override
	public void run() {
		TestBean.staticSyncMethodA("SSA");
	}
	
}
class ThreadSSB extends Thread{

	@Override
	public void run() {
		TestBean.staticSyncMethodB("SSB");
	}
	
}
メールの方法を修正します。
public static void main(String[] args) {
		
		TestBean testBean = new TestBean();
		ThreadDSA dsa = new ThreadDSA(testBean);
		ThreadSSB ssb = new ThreadSSB();
		ThreadSSA ssa = new ThreadSSA();
		dsa.start();
		SleepUtil.sleep(1);
		ssb.start();
		ssa.start();
	}
実行結果は以下の通りです
参照
I'm static synchronized methodB
Now field is:SSB
I'm static synchronized methodA
Now dynamicfield is:DSA
Now static field is:DSA
Now field is:SSA
静的方法と動的方法のロックは違っています。動的方法は動的方法とのみ同期します。静的方法は静的方法とのみ同期します。
要約すると、動的方法声明にsynchronizedフィールドを追加すると、このオブジェクトのインスタンスのロックが実行中に獲得され、この例のすべてのsynchronized方法はロックが解除される前に実行できなくなりますが、他の例では、この例の非同期方法と静的方法は影響を受けません。
これは本シリーズの最初の文章で、主に同じ種類の中で、声明方法にsynchronizedキーワードを入れる役割を説明しています。これからの文章では、synchronizedの他の用法と複数の種類の間でsynchronizedキーワードの役割をテストします。