クラスロックとオブジェクトロックは競合しますか?オブジェクト ロックとプライベート ロックは競合しますか?例を通して説明します。
1. 関連規約
以下の説明を明確にするために、この記事に含まれるロックの関連定義に関して以下の規約が定められています:
1. クラス ロック: 静的ロックと同期ロックがメソッドに追加されます。コードまたは synchronized(xxx.class) のコード セグメント (以下の increamment() など) 2. オブジェクト ロック: コード内のメソッドに同期ロックを追加するか、synchronized(this) のコード セグメントを追加します。 synOnMethod () および synInMethod(); として
3. プライベート ロック: クラス内でプライベート オブジェクト ロックなどのプライベート プロパティを宣言し、ロックする必要があるコード セグメント (以下の synMethodWithObj() など) を同期(ロック)します。 。
2. テストコード
1. 起動クラス ObjectLock を作成します
public class ObjectLock { public static void main(String[] args) { System.out.println("start time = " + System.currentTimeMillis()+"ms"); LockTestClass test = new LockTestClass(); for (int i = 0; i < 3; i++) { Thread thread = new ObjThread(test, i); thread.start(); } } }
2. 同期メソッドを開始するスレッド クラス ObjThread を作成します (その実行メソッドは異なるテストに合わせて調整される可能性があることに注意してください)
public class ObjThread extends Thread { LockTestClass lock; int i = 0; public ObjThread(LockTestClass lock, int i) { this.lock = lock; this.i = i; } public void run() { //无锁方法 // lock.noSynMethod(this.getId(),this); //对象锁方法1,采用synchronized synInMethod的方式 lock.synInMethod(); //对象锁方法2,采用synchronized(this)的方式 // lock.synOnMethod(); //私有锁方法,采用synchronized(object)的方式 // lock.synMethodWithObj(); //类锁方法,采用static synchronized increment的方式 LockTestClass.increment(); } }
3.ロック テスト クラス LockTestClass (さまざまなロック メソッドを含む)
public class LockTestClass { //用于类锁计数 private static int i = 0; //私有锁 private Object object = new Object(); /** * <p> * 无锁方法 * * @param threadID * @param thread */ public void noSynMethod(long threadID, ObjThread thread) { System.out.println("nosyn: class obj is " + thread + ", threadId is" + threadID); } /** * 对象锁方法1 */ public synchronized void synOnMethod() { System.out.println("synOnMethod begins" + ", time = " + System.currentTimeMillis() + "ms"); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("synOnMethod ends"); } /** * 对象锁方法2,采用synchronized (this)来加锁 */ public void synInMethod() { synchronized (this) { System.out.println("synInMethod begins" + ", time = " + System.currentTimeMillis() + "ms"); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("synInMethod ends"); } } /** * 对象锁方法3 */ public void synMethodWithObj() { synchronized (object) { System.out.println("synMethodWithObj begins" + ", time = " + System.currentTimeMillis() + "ms"); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("synMethodWithObj ends"); } } /** * 类锁 */ public static synchronized void increament() { System.out.println("class synchronized. i = " + i + ", time = " + System.currentTimeMillis() + "ms"); i++; try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("class synchronized ends."); } }
3. テスト結果
1. クラス ロックとオブジェクト ロックをテストするには、ObjectThread の run メソッドを次のように変更します。
public void run() { //无锁方法 // lock.noSynMethod(this.getId(),this); //对象锁方法1,采用synchronized synInMethod的方式 lock.synInMethod(); //对象锁方法2,采用synchronized(this)的方式 // lock.synOnMethod(); //私有锁方法,采用synchronized(object)的方式 // lock.synMethodWithObj(); //类锁方法,采用static synchronized increment的方式 LockTestClass.increament(); }
ターミナル出力:
start time = 1413101360231ms synInMethod begins, time = 1413101360233ms synInMethod ends class synchronized. i = 0, time = 1413101362233ms synInMethod begins, time = 1413101362233ms class synchronized ends. synInMethod ends class synchronized. i = 1, time = 1413101364233ms synInMethod begins, time = 1413101364233ms class synchronized ends. synInMethod ends class synchronized. i = 2, time = 1413101366234ms class synchronized ends.
を確認できます。オブジェクト ロック メソッド (synInMothod) は、最初の起動時にクラス ロック メソッド (increamment) より 2 秒高速です。これは、synInMehtod の実行時に 2 秒間スリープしてから increamment を実行し、これら 2 つのメソッドが共有するためです。したがって、実行時に increamment が synInMethod の前に配置されると、increamment が初めて開始されるときは 2 秒速くなります。
クラス ロック メソッドが開始されると、別のスレッドのオブジェクト ロック メソッドもほぼ同時に開始されます。これは、2 つが同じロックを使用しておらず、競合がないことを示します。
結論: クラス ロックとオブジェクト ロックは競合せず、それらのロック方法は相互に影響しません。
2. プライベート ロックとオブジェクト ロック、ObjectThread の run メソッドは次のように変更されます:
public void run() { //无锁方法 // lock.noSynMethod(this.getId(),this); //对象锁方法1,采用synchronized synInMethod的方式 lock.synInMethod(); //对象锁方法2,采用synchronized(this)的方式 // lock.synOnMethod(); //私有锁方法,采用synchronized(object)的方式 lock.synMethodWithObj(); //类锁方法,采用static synchronized increment的方式 // LockTestClass.increament(); }
ターミナル出力:
start time = 1413121912406ms synInMethod begins, time = 1413121912407ms. synInMethod ends. synMethodWithObj begins, time = 1413121914407ms synInMethod begins, time = 1413121914407ms. synInMethod ends. synMethodWithObj ends synInMethod begins, time = 1413121916407ms. synMethodWithObj begins, time = 1413121916407ms synInMethod ends. synMethodWithObj ends synMethodWithObj begins, time = 1413121918407ms synMethodWithObj ends
はクラス ロックとオブジェクト ロックに非常に似ています。
結論: プライベート ロックとオブジェクト ロックは競合せず、それらのロック方法は相互に影響しません。
3.synchronized がメソッドに直接追加され、synchronized(this) されます。ObjectThread の run メソッドは次のように変更されます。
public void run() { //无锁方法 // lock.noSynMethod(this.getId(),this); //对象锁方法1,采用synchronized synInMethod的方式 lock.synInMethod(); //对象锁方法2,采用synchronized(this)的方式 lock.synOnMethod(); //私有锁方法,采用synchronized(object)的方式 // lock.synMethodWithObj(); //类锁方法,采用static synchronized increment的方式 // LockTestClass.increament(); }
ターミナル出力:
start time = 1413102913278ms synInMethod begins, time = 1413102913279ms synInMethod ends synInMethod begins, time = 1413102915279ms synInMethod ends synOnMethod begins, time = 1413102917279ms synOnMethod ends synInMethod begins, time = 1413102919279ms synInMethod ends synOnMethod begins, time = 1413102921279ms synOnMethod ends synOnMethod begins, time = 1413102923279ms synOnMethod ends
ご覧のとおり、2 つの出力は厳密にシリアルに行われます (もちろん、再実行時に最初に実行 synInMethod と synOnMethod のどちらが最初に実行されるかは定かではなく、誰がロックを取得するかによって異なります。
結論: メソッドに直接追加される synchronized と現在のオブジェクトをロックする synchronized(this) の両方は、同時に実行できるメソッドは 1 つだけです。
Java クラス ロック、オブジェクト ロック、プライベート ロックの競合テストに関連するその他の記事については、PHP 中国語 Web サイトに注目してください。