ホームページ >Java >&#&チュートリアル >同期キーワードの使用
synchronized キーワードは、Java 同時プログラミングで一般的に使用される同期ロックです。メソッドまたはコード ブロックをロックするために使用されます。コード ブロックをロックする場合は、synchronized(this){}、synchronized(Object){}、synchronized を使用できます。 (クラス) {}。
#ロックされたコンテンツが実行されるか、実行中に例外がスローされると、ロックは自動的に解放されます。
手動でロックを解放したい場合は、ロックされたオブジェクトの wait() メソッドを呼び出してロックを解放して待機状態にし、他のスレッドに切り替えて実行する必要があります。 () メソッドは、他のスレッドの wait() メソッドと呼び出されたオブジェクトを起動するだけですが、ロックは解放されず、選択順序はコードによって制御されず、仮想マシンによって実装されます。
したがって、オブジェクトの wait()、notify()、および NoticeAll() メソッドは、スレッド間のスケジューリングを完了するために synchronized キーワードとともにのみ使用できます。
ロックされたメソッドは、次のように synchronized(this){コード ブロックとしてのメソッドのすべてのコード} と同等です。
public synchronized void test() { ... }
上記と同等たとえば、ロックされている例は、このクラスのオブジェクトです。静的メソッドがロックされている場合、その静的メソッドはオブジェクトではなくクラスに属していることがわかります。したがって、synchronized によって変更された静的メソッドは、このクラスのすべてのオブジェクトをロックします。 、このクラスに属している限り、2 つの Instance オブジェクトであってもロックされます。
public void test() { synchronized (this) { ... } }
public synchronized static void test() { ... }
と同等 コード ブロックをロックするときの参照オブジェクトがロック メソッドであっても、コード ブロックであっても、1 つの原則を覚えていれば明らかです。つまり、参照オブジェクトが同じである場合にのみ同期ロックが機能し、それ以外の場合、ロックは相互に排他的ではなく、同時に実行できます。
synchronized(this) は、現在のクラスのオブジェクト インスタンスが同じである場合にロックが有効になることを示し、synchronized(Object) は、Object オブジェクトが同じである場合にロックが有効になることを示し、synchronized(class ) は、すべてが同じクラスである場合にロックが有効になることを示します。
簡単な例を示します:
public static void test() { synchronized (所在类.class) { ... } }
上記のコードでは、参照オブジェクト str は "1" です。Java では、文字列文字列が this.str="1" を渡すと、代入は次のようになります。 str=String.valueOf("1") と同等。文字列 "1" が以前に初期化されている場合は、前のものが直接取得されるため、同じオブジェクトになります。上で紹介した原理によれば、ロックがかかるため、結果は 3 秒後に 1 が出力され、さらに 3 秒後に 1 が出力されます。
スレッド 2 が
public class TestController { public class Task implements Runnable{ private String str; Task(String str){ this.str=str; } @Override public void run() { synchronized (str) { try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(str); } } } public static void main(String[] args) throws InterruptedException { TestController testController = new TestController(); Thread thread1 = new Thread(testController.new Task("1")); Thread thread2 = new Thread(testController.new Task("1")); thread1.start(); thread2.start(); } }
に変更された場合、参照オブジェクトの一方は「1」、もう一方は「2」となり、同じオブジェクトではないため、相互にロックされません。排他的で動作しないため、結果は 3 秒後に 1 と 2 がほぼ同時に出力されます。
上記はすべて、同じメソッドを同時に呼び出す複数のスレッドです。異なるメソッドが呼び出された場合はどうなるでしょうか?
Thread thread2 = new Thread(testController.new Task("2"));
上記のコードの出力結果は次のとおりです:
public class Test{ public synchronized void m1(){ System.out.println("m1 running..."); try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("m1 end"); } public synchronized void m2(){ System.out.println("m2 running..."); System.out.println("m2 end"); } public static void main(String[] args) { Test test = new Test(); new Thread(new Runnable() { @Override public void run() { test.m1(); } }).start(); new Thread(new Runnable() { @Override public void run() { test.m2(); } }).start(); } }
前述のように、同期された変更は synchronized(this){コード ブロックとしてのメソッドのすべてのコード} と同等です。これは、オブジェクトであることを表します。つまり、最初のスレッドがテスト オブジェクトのロックを取得します。オブジェクトはすべて同じテストであるため、2 番目のスレッドはロックを取得できず、ブロックされます。
上記の例を次のように変更します。
m1 running... //过3秒 m1 end m2 running... m2 end
最初のスレッドが m1() を呼び出すと、オブジェクト str のロックが取得され、2 番目のスレッドも m2 を呼び出すときにそれが必要になります。 () オブジェクト str のロックを取得します。これらは同じ Test オブジェクトであるため、2 つの str も同じオブジェクトであるため、2 番目のスレッドはロックを取得できないためブロックされ、出力結果は同じになります。前の例のように。
上記の例を次のように変換すると:
private String str = "1"; public void m1(){ synchronized(str){ System.out.println("m1 running..."); try { Thread.sleep(3000l); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("m1 end"); } } public void m2(){ synchronized(str){ System.out.println("m2 running..."); System.out.println("m2 end"); } }
今回呼び出されるメソッドは 2 つのクラスにありますが、ロックされているため、結果は前の 2 つの例と同じになります。渡されたすべての str オブジェクト。同じオブジェクトのロックは 1 つだけです。最初のスレッドがそれを取得すると、2 番目のスレッドは待機することしかできません。
概要:A. synchronized キーワードがメソッドに追加されるかオブジェクトに追加されるかに関係なく、そのキーワードが作用するオブジェクトが非静的である場合、ロックは取得されるのはオブジェクトです ; 同期されたオブジェクトが静的メソッドまたはクラスの場合、取得されるロックはそのクラス用であり、そのクラスのすべてのオブジェクトは同じロックを持ちます。
B. 各オブジェクトにはロックが 1 つだけ関連付けられており、このロックを取得した人は、そのロックが制御するコードを実行できます。
C. 同期を実現するには多くのシステム オーバーヘッドが必要であり、デッドロックが発生する可能性もあるため、不必要な同期制御は避けるようにしてください。
以上が同期キーワードの使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。