1

2つの間に違いはありますか:

public void synchronized func() {
}

public void func() {
   synchronized(this) {
   }
}

最初のケースでは関数全体funcが同期され、2 番目のケースでは関数のコードの一部のみが同期されることを理解しています。しかし、違いはありますか?つまり、命令は常に次々に実行されます。スレッドが同期ブロックに到達したときにロックを取得できなくても、同期ブロックの後に操作を開始することはありません。

機能的な違いはまったくありますか、それとも単なる良い習慣ですか?

4

6 に答える 6

4

2 番目のケースでは、関数のコードの一部のみが同期されます。しかし、違いはありますか?

はい、同期部分の外側に多くのコードがある場合、違いがあります。

public void func() {
   someHeavyOperations();
   synchronized(this) {
      criticalSectionOperations();
   }
   someMoreHeavyOperations();
}

クリティカル セクションをできるだけ小さくしたい。

スレッドが同期ブロックに到達したときにロックを取得できなくても、同期ブロックの後に操作を開始することはありません。

いいえ。ただし、同期ブロックの前に操作を完了することができます。また、同期ブロックの後の操作を実行している間、誰も待たせることもありません。

this同期されたブロックの外側にこれ以上コードがない場合でも、たとえばロックを非公開にしたり、より細かくしたりするために、以外のもので同期できるため、この構造は便利です。

于 2012-09-14T09:02:54.160 に答える
2

上記に実質的な違いはないと思います。

ただし、より柔軟であるため、後者を好みます。包含オブジェクト ( ) をロックする代わりにthis、特定のロック オブジェクトをロックすることができ、さまざまなメソッドでさまざまなロック オブジェクトを指定できます (同期要件によって異なります)。これは、必要に応じて同期をよりきめ細かく調整できることを意味します。

例えば

public synchronized void doSomething() {
   ...
}

(ロックオンthis)

対。

public void doSomething() {
   synchronized(someLockObject) {
      ...
   }
}
于 2012-09-14T09:03:17.760 に答える
0

メソッドの内容全体を同期している場合、機能的な違いはありません。メソッドの一部のみを同期する場合は、同期の範囲が異なります。

同期ブロックの後のコードが同期ブロックの前に実行されないことは正しいです。ただし、スレッドは、同期されていない任意の時点でスワップアウトできます。次の点を考慮してください。

synchronized (this) {
    //sycnronized bit
}
// some other code

2 つのスレッドがあり、A と B があり、A がロックを取得すると、B は A が同期ブロックを終了するまでブロックされます。ただし、A は、このブロックを終了するとすぐにスワップ アウトされる可能性があります。その後、B は同期ブロックに入り、A がスワップインされる前に機能を完了することができます。

これは非常に一般的に使用できます。たとえば、複数のスレッドが高価な計算を実行できるようにしながら、可変インスタンス変数が計算の範囲で一貫していることを確認する場合などです。例えば

Object localCopy;
synchronized (this) {
    localCopy = this.instanceVar;
}
// expensive calculation using localCopy which won't change even if instanceVar is changed.
于 2012-09-14T09:08:17.967 に答える
0

あなたは保つ必要がありますCritical Section as small as possible. so synchronized(this) is more useful

ただし、クリティカル セクションがメソッドの場合は、先に進んでメソッドを次のように宣言できます。synchronized

1.5 以降では、いつでもReentrantLockを使用できます。

同期されたメソッドとステートメントを使用してアクセスされる暗黙的な監視ロックと同じ基本的な動作とセマンティクスを持つ再入可能な相互排除ロックですが、拡張機能があります。

class X {
private final ReentrantLock lock = new ReentrantLock();
// ...

public void m() { 
  lock.lock();  // block until condition holds
  try {
    // ... method body
  } finally {
    lock.unlock()
  }
}
}
于 2012-09-14T09:07:35.360 に答える
0

ロックの観点からは、違いはありません。

バイト コードの観点からは、最初のメソッドがリフレクションまたはほとんどのクラス ビューアを使用して同期されていることがわかります。2 番目のケースは、そうであると判断するのがより困難です。

使用されているロックを非表示にしたい場合、つまりthis呼び出し元が混乱しないように使用していない場合は、ブロック同期が優先されます。

于 2012-09-14T09:02:32.023 に答える
0

JLS http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6を引用するには

したがって、コードは次のとおりです。

synchronized void bump() {
    count++;
}

以下とまったく同じ効果があります。

void bump() {
    synchronized (this) { count++; }
}
于 2012-09-14T16:45:42.220 に答える