ホームページ  >  記事  >  Java  >  Java クラス ロック、オブジェクト ロック、プライベート ロックの競合テスト

Java クラス ロック、オブジェクト ロック、プライベート ロックの競合テスト

高洛峰
高洛峰オリジナル
2017-01-19 13:41:401305ブラウズ

クラスロックとオブジェクトロックは競合しますか?オブジェクト ロックとプライベート ロックは競合しますか?例を通して説明します。

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 サイトに注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。