2

メソッド「calculate()」を持つクラス「A」があります。クラス A はシングルトン型 (Scope=Singleton) です。

public class A{ 

public void calculate(){
   //perform some calculation and update DB
 }

}

これで、20 個のスレッドを作成するプログラムができました。すべてのスレッドがメソッド「calculate()」にアクセスする必要があります。私はマルチコアシステムを持っています。したがって、スレッドの並列処理が必要です。

上記のシナリオで、パフォーマンスを得ることができますか? すべてのスレッドがメソッド計算に同時にアクセスできますか?

または、クラスAはシングルトンなので、スレッドをブロックして待機する必要があります。

web/Stackoverflow で同様の質問を見つけました。しかし、明確な答えは得られません。助けてくれませんか?

4

5 に答える 5

3

「シングルトンには同期が必要」または「シングルトンには同期が必要ない」などのステートメントは、あまりにも単純すぎると思います。シングルトン パターンを扱っているという事実だけからは、結論を導き出すことはできません。

マルチスレッドの目的で本当に重要なのは、何を共有するかです。計算を実行するすべてのスレッドで共有されるデータがある場合は、おそらくそのアクセスを同期する必要があります。スレッド間で同時に実行できないコードのクリティカル セクションがある場合は、それを同期する必要があります。

幸いなことに、多くの場合、計算全体ですべてを同期する必要はありません。操作の一部を同期する必要があるにもかかわらず、マルチコア システムから大幅なパフォーマンスの向上が得られる場合があります。

悪いニュースは、これらが非常に複雑であることです。ごめん。1 つの可能な参照:

http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601/ref=sr_1_1?ie=UTF8&qid=1370838949&sr=8-1&keywords=Java+concurrency+in+practice

于 2013-06-10T04:38:19.040 に答える
2

それが Singleton の基本概念です。システム (JVM) には、クラスのインスタンスが 1 つだけ存在します。現在は、calculate() の実装に依存しています。ステートレスなユーティリティメソッドですか? はいの場合、同期させたくない場合があります。その場合、複数のスレッドが同時にアクセスできます。calculate() がステートレスでない場合、つまりインスタンス変数を使用している場合 (およびそれらのインスタンス変数が複数のスレッドで使用される場合) は、注意してください。calculate() をスレッドセーフにする必要があります。メソッドを同期する必要があります。少なくとも、メソッド内で同期ブロックを使用する必要があります。ただし、これを行うと、任意の時点で 1 つのスレッド (同期ブロックまたはメソッド内の同期ブロック) のみがアクセスできます。

public void calculate() {

    //Some code goes here which does not need require thread safety.
    synchronized(someObj) {
        //Some code goes here which requires thread safety.
    }
    //Some code goes here which does not need require thread safety.
}

並列処理を使用する場合 (それが主な目的である場合)、シングルトンは使用すべき設計パターンではありません。

于 2013-06-10T04:37:07.283 に答える
1

web/Stackoverflow で同様の質問を見つけました。しかし、明確な答えは得られません。

それにはちゃんとした理由があります!!

singleton のメソッドが singleton であるために同期する必要があるかどうかを判断することはできません。

同期と同期の必要性は、異なるスレッドによって共有される可能性のある状態に関するものです。

  • 異なるスレッドが状態を (シリアルでも) 共有する場合は、同期が必要です。

  • そうでない場合、同期は必要ありません。


はい/いいえの答えを与えるのに役立つ唯一の手がかりは、次の謎めいたコメントです。

  // perform some calculation and update DB

...そして、calculate()メソッドが引数を取らないという事実。

メソッドがシングルトン自体の状態から入力を取得すると推測する場合、calculate()メソッドの少なくとも一部 (またはそれが呼び出すメソッド) は、その状態を取得する際に同期する必要があります。ただし、これは、メソッド呼び出し全体を同期する必要があるという意味ではありません。メソッドが共有データのロックを保持するために必要な時間の割合によって、calculate実際に取得できる並列処理の量が決まります...

データベースの更新には、ある種の同期も必要です。ただし、これは JDBC 接続オブジェクトとそこから取得するオブジェクトによって処理される必要があります...ただし、ルールに従い、複数のスレッド間で接続を共有しようとしないことが条件です。(データベースの更新は、並行性のボトルネックも示します...更新が同じデータベーステーブルまたは複数のテーブルに適用されると仮定します。)

于 2013-06-10T05:28:34.943 に答える
0

シングルトンをどのように実装するかによって異なります。Synchronized キーワードを使用すると、待機します。熱心な初期化でシングルトンを使用します。

このようなもの:

public final class Universe {

  public static Universe getInstance() {
     return fINSTANCE;
  }

  // PRIVATE //

  /**
  * Single instance created upon class loading.
  */
  private static final Universe fINSTANCE =  new Universe();

  /**
  * Private constructor prevents construction outside this class.
  */
  private Universe() {
    //..elided
  }
} 

上記は、マルチスレッド環境で非常にうまく機能します。または、Singleton の enum 実装に進むことができます。

さまざまなシングルトンの実装については、このリンクを確認してください: http://javarevisited.blogspot.in/2012/07/why-enum-singleton-are-better-in-java.html

于 2013-06-10T04:26:03.467 に答える
0

複数のスレッドが同時に calculate() を呼び出すことができます。

これらの呼び出しは、何らかのタイプの同時実行制御を実行しない限り、その JVM 内でキューに入れられる (シリアルに実行される) ことはありません (メソッドを作成することsynchronizedは 1 つのオプションです)。

オブジェクトがシングルトンであるという事実は、そのオブジェクトの属性 (存在する場合) が calculate() 内でどのように使用されるかによって、パフォーマンスに影響する場合と影響しない場合があります。

また、「DB を更新」しているため、テーブルまたは行レベルのロックも同時実行を制限する可能性があることに注意してください。

パフォーマンスが心配な場合は、テストすることをお勧めします。

于 2013-06-10T06:12:10.090 に答える