1

私はの概念が明確ではありません

Javaスレッドは、インスタンス同期Javaメソッドに入るときにオブジェクトレベルのロックを取得し、静的同期Javaメソッドに入るときにクラスレベルのロックを取得します。

オブジェクトレベルのロックとクラスレベルのロックとはどういう意味ですか?

例えば:

 public class Counter{
      private static int count = 0;
      private int count2 = 0;

      public static synchronized int getCount(){
           return count;
      }
      public synchronized setCount(int count2){
           this.count2 = count2;
      }
 } 

ここでgetCount()はCounter.classオブジェクトをロックし、setCount()は現在のobject(this)をロックします。これは何を指しますか?これは、getCount()が呼び出されると、クラス全体がロックされているため、別のスレッドがsetCount()にアクセスできないことを意味しますか?

4

4 に答える 4

1

Javaの各オブジェクトにはミューテックスがあります。aclassはタイプのオブジェクトで表されるためjava.lang.Class、各クラスにもミューテックスがあります。 synchronizedインスタンスメソッドはインスタンスのミューテックスをsynchronized staticロックし、メソッドは対応するjava.lang.Classインスタンスのミューテックスをロックします。

class C {
  synchronized T myMethod() { ... }

  static synchronized T myStaticMethod() { ... }
}

と同等です

class C {
  T myMethod() {
    synchronized (this) { ... }  // An object level lock.
  }

  static T myStaticMethod() {
    synchronized (C.class) { ... }  // A class level lock
    // is really just an object level lock an a Class.
  }
}

同期しているオブジェクトがわかれば、synchronizedキーワードを分類して理解できます。

synchronized (x) {
  body();
}

のように実行します

monitorenter(x);  // locks x or throws NullPointerException if x is null.
try {
  body();
} finally {
  monitorexit(x);  // unlocks x
}

ここでmonitorenter、およびmonitorexitは、ミューテックスを取得してミューテックスを解放するまでそれぞれブロックするJavaバイトコード命令です。

synchronizedのような「保護された領域」が導入されるためtry ... finally、例外がスローされてもロックは解放されますが、スレッドを強制終了するとロックが解放されないままになり、デッドロックが発生する可能性があります。

于 2012-08-21T22:45:39.657 に答える
1

Javaでは、各クラスとクラスの各インスタンスに固有のロックが付与されています。synchronizedこれらは、メソッドに出入りするときに取得および解放されるロックです。

いつものように、呼び出さthisれたインスタンスを指しますsetCount()。各インスタンスには独自の固有のロックがあるため、2番目の呼び出しsetCount()は、クラスの別のインスタンスで呼び出されている限りブロックされませんが、別のインスタンスで呼び出されようとしsetCount()ます。setCount()通話中はブロックされます。

クラスロックとインスタンスロックは異なるため、お互いに邪魔になることはgetCount()ありません。setCount()

于 2012-08-21T22:37:51.240 に答える
1

staticメンバーは、特定のインスタンスではなくクラスに関連付けられています。結果として、static静的はクラスメンバーであるため、メンバーの同期はクラス全体で効果的に同期されます。

インスタンスメンバーはクラスのインスタンスに関連付けられているため(たとえば、イントリシックthisロック)、メンバーフィールド(非静的)またはで同期する場合thisは、インスタンスオブジェクトに関連付けられたロックがあります。

あなたの例getCountでは、クラスのintrinsikロックで同期します。効果的にあなたはしている:

public setCount(int count){
    synchronized(this){
        this.count = count;
    }  
}

次の場合、クラスレベルで同期します。

static Object count = new Object();  
synchronized(count){  

}
于 2012-08-21T22:40:58.737 に答える
1

オブジェクトレベルのロックとクラスレベルのロックとはどういう意味ですか?

staticメソッドをロックすると、オブジェクト自体がロックされ、ごとClassにこれらの1つがありますClassLoader。あなたの例では、

public static synchronized int getCount(){

これはオブジェクトをロックしておりCounter.class、次と同じです。

public static int getCount() {
    synchronized (Counter.class) {
    }

代わりに、そうでない staticメソッドをロックしている場合は、そのメソッドを所有しているオブジェクトのインスタンスをロックしています。あなたの例では:

public synchronized void setCount(int count){

これは、特定のインスタンスをロックすることと同じであり、Counter次と同等です。

public void setCount(int count){
    synchronized (this) {
       ...

したがって、2つCounterのオブジェクトがcounter1ありcounter2、1つのスレッドが呼び出しcounter1.getCount()ていて、もう1つのスレッドがcounter2.getCount()同時に呼び出している場合、それらは両方とも同じClassオブジェクトをロックし、一方が他方をブロックします。

しかし、2つのスレッドが代わりに呼び出しcounter1.setCount(...)ていて、それぞれcounter2.setCount()異なるオブジェクトをロックしている場合。それらは互いにブロックしません。counter1counter2

前述のように、セッターとゲッターに非対称性があるのは非常に悪い形式であり、どちらかが非対称であるのは珍しいことstaticです。

これは、getCount()が呼び出されると、クラス全体がロックされているため、別のスレッドがsetCount()にアクセスできないことを意味しますか?

いいえ。getCount()が呼び出されCounter.classた場合はロックされ、setCount(...)が呼び出されたcounter1場合counter2はロックされます。ロックがスレッドをブロックするのは、同じオブジェクトが別のスレッドによってロックされている場合のみです。ロックがオンになっているからといって、ある種の超クラスのロックがあることを意味するわけではありCounter.classません。別のスレッドをブロックするのは、それがロックしすぎている場合のみCounter.classです。

動作方法に関するSunの優れたドキュメントをsynchronized少し読んでみます。

于 2012-08-22T14:36:27.583 に答える