JAvaのSynchronized(オブジェクトのロックとコードのロック)
3486 ワード
1、問題
Synchronizedロックは一般的に知られていますが、ロックオブジェクトかロックコードかをどのように区別しますか?
2、テストDemo
3、運行結果と分析
1)、上記の運転結果による
2)、forループ内のコードを次のように変更します.
実行結果は次のとおりです.
上記1)、2)、両方の場合、synchronized(this)およびstatic以外のsynchronizedメソッドでは、複数のスレッドが同じオブジェクトの同期コードセグメントを同時に実行することを防止するしかなく、ロックされているのはオブジェクト、すなわちロックされている自体thisであり、各スレッドに新しいオブジェクトが構築されているため、synchronizedがロックされていない.
3)、forループ内のコードを次のように変更します.
実行結果は次のとおりです.
ここでは,我々のいくつかのフィールドが1つのオブジェクトを共有しているため,オブジェクトが固定されているため,ロックがロックされており,他のスレッドはロックを解放していない間に入らない.
4)、forループ内のコードを次のように変更します.
結果は以下の通りです.
synchronized(Test.class)はグローバルロックの効果を実現し、オブジェクトが同じかどうかにかかわらず、同じ効果でコードをロックしました
私は普通これを使うのが多いです.
4、まとめ
1、synchronized非静的メソッドに追加する前とsynchronized(this)はこのクラスをロックしたオブジェクトであり、マルチスレッドアクセスでオブジェクトが異なるとロックできず、オブジェクトが1つ固定されているとロックできます.
2、synchronized(クラス名.class)と静的メソッドに追加する前に、コードブロックをロックし、マルチスレッドアクセス時にオブジェクトが同じかどうかにかかわらず、コードセグメントを縮小できる範囲をできるだけ縮小し、コードセグメントに同期を追加できるようにするには、メソッド全体に同期を追加しないで、ロックの粒度を縮小します.
4、まとめ
Synchronizedロックは一般的に知られていますが、ロックオブジェクトかロックコードかをどのように区別しますか?
2、テストDemo
package leetcode.chenyu.test;
public class Synchronized {
class Test {
public synchronized void testFirst() {
print("testFirst");
}
public void testSecond() {
synchronized(this) {
print("testSecond");
}
}
public void testThird() {
synchronized(Test.class) {
print("testThird");
}
}
public void print(String method) {
System.out.println(method + "start");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(method + "end");
}
}
class TestThread extends Thread {
public int mType = 0;
public Test mTest = null;
public TestThread(int type, Test test) {
this.mType = type;
this.mTest = test;
}
public void run() {
if (mTest == null) {
if (mType == 1) {
Test test = new Test();
test.testFirst();
}
else if (mType == 2) {
Test test = new Test();
test.testSecond();
}
else if (mType == 3) {
Test test = new Test();
test.testThird();
}
} else {
if (mType == 1) {
mTest.testFirst();
}
else if (mType == 2) {
mTest.testSecond();
}
else if (mType == 3) {
mTest.testThird();
}
}
}
}
public static void main(String[] args) {
Synchronized syn = new Synchronized();
Test test = syn.new Test();
for (int i = 0; i < 5; ++i) {
syn.new TestThread(1, null).start();
}
}
}
3、運行結果と分析
1)、上記の運転結果による
testFirststart
testFirststart
testFirststart
testFirststart
testFirststart
testFirstend
testFirstend
testFirstend
testFirstend
testFirstend
2)、forループ内のコードを次のように変更します.
syn.new TestThread(2, null).start();
実行結果は次のとおりです.
testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondend
testSecondend
testSecondend
testSecondend
testSecondend
上記1)、2)、両方の場合、synchronized(this)およびstatic以外のsynchronizedメソッドでは、複数のスレッドが同じオブジェクトの同期コードセグメントを同時に実行することを防止するしかなく、ロックされているのはオブジェクト、すなわちロックされている自体thisであり、各スレッドに新しいオブジェクトが構築されているため、synchronizedがロックされていない.
3)、forループ内のコードを次のように変更します.
syn.new TestThread(1, test).start();
syn.new TestThread(2, test).start();
実行結果は次のとおりです.
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
ここでは,我々のいくつかのフィールドが1つのオブジェクトを共有しているため,オブジェクトが固定されているため,ロックがロックされており,他のスレッドはロックを解放していない間に入らない.
4)、forループ内のコードを次のように変更します.
syn.new TestThread(3, null).start();
syn.new TestThread(3, test).start();
結果は以下の通りです.
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
synchronized(Test.class)はグローバルロックの効果を実現し、オブジェクトが同じかどうかにかかわらず、同じ効果でコードをロックしました
私は普通これを使うのが多いです.
4、まとめ
1、synchronized非静的メソッドに追加する前とsynchronized(this)はこのクラスをロックしたオブジェクトであり、マルチスレッドアクセスでオブジェクトが異なるとロックできず、オブジェクトが1つ固定されているとロックできます.
2、synchronized(クラス名.class)と静的メソッドに追加する前に、コードブロックをロックし、マルチスレッドアクセス時にオブジェクトが同じかどうかにかかわらず、コードセグメントを縮小できる範囲をできるだけ縮小し、コードセグメントに同期を追加できるようにするには、メソッド全体に同期を追加しないで、ロックの粒度を縮小します.
4、まとめ