0

マルチスレッド コードで同期を使用する本当の理由を理解しようとしています。

複数のスレッドが共通の共有リソースに同時にアクセスすると、デッドロックや競合状態などの多くの問題が発生することがわかっていますが、複数のスレッドによって呼び出されるコードを同期すると、1 つのスレッドのみがリソースにアクセスできるようになります。他のスレッドはキューで待機します。この場合、これは同期のないシングル スレッド アプリケーションと同じです。マルチスレッド コードを同期すると、どのようなパフォーマンスが得られるでしょうか?

2 つのシナリオを比較するための単なる例 1. 1 つのレコードを処理するのに 1 秒かかると仮定して、1 つのスレッド モデルで 1000 のレコードを処理する必要があるため、合計で 1000 秒かかります。2. マルチスレッド モデルで 1000 レコードを処理する必要があります。プロセス メソッドは同期されます。1 つのレコードを処理するのに 1 秒かかると仮定し、10 スレッドが生成されると仮定します。したがって、ここでも、スレッドが同期にアクセスするたびにメソッド、残りのスレッドはキューに入れられ、完了するまでに合計で 1000 秒かかります。

誰かがこの基本を理解してくれたら、私は本当に満足し、安心します. ありがとう、

編集:

プログラミング言語については触れていません: その Java

以下のコードの同期の影響と同期なしの影響を理解するためだけに (Spring Batch の例):

package com.dbas.core;
import java.util.List;
import org.springframework.batch.item.ItemReader;

public class NextReader implements ItemReader<String> {       
    private List<String> itemList;
    public NextReader(ListBean listBean) {
        itemList = listBean.getItemList();
    }
    public synchronized String read()
    {           
        if (!itemList.isEmpty()) {
                  return itemList.remove(0);
        }
        return null;
    }   
} 

上記のコードを同期する必要がありますか? そうでない場合、インスタンス変数「itemList」は複数のスレッドで共有されます。共有されている場合、上記のアイテムの取得は正しく機能しますか? アイテムを処理する read() の後に呼び出されるプロセッサがあります。複数のスレッドに対して上記のコードを同期することはお勧めですか、それとも同期しなくても問題なく動作しますか?

ありがとう。

4

3 に答える 3

0

もちろん、ミューテックスを保持する時間が残りのコードに比べて非常に長い場合は、マルチスレッドの利点が失われます。極端な例として、スレッドがミューテックスを永久に保持するアプリケーションを考えてみましょう。シングル スレッド アプリケーションが得られます。

このため、ソフトウェア開発者は通常、ロックをできるだけ短時間維持するようにコードを設計します。たとえば、ダブル チェック ロック パターンを参照してください: http://en.wikipedia.org/wiki/Double-checked_locking

より複雑な状況では、データの読み取りと書き込みを行う複数のスレッドが存在する場合でも、優れたパフォーマンスを実現できるデータ構造が存在します。たとえば、Linux カーネルにも実装されている RCU データ構造を参照してください: http://en.wikipedia.org/wiki/Read-copy-update

于 2013-06-10T13:08:18.497 に答える
0

マルチスレッド コードでの同期は、異なるスレッド間のリソースの安全な共有状態アクセスを可能にするために使用されます。言語とハードウェアの実装の詳細に応じて、多くの異なるスレッドによる共有状態へのアクセスには、次の危険があります。

  1. 2 つのスレッドが同時に同じメモリ位置を読み書きしようとすると、データが破損します。
  2. 可視性の副作用。あるスレッドが共有リソースの状態を変更した場合、その変更は、適切な同期がなければ、すぐに (またはまったく) 他のスレッドに明らかにならない場合があります。これは、コンパイラの最適化 (命令の並べ替え) が原因で発生することもあります。

あなたの質問は漠然としていると言いましたが、特定のプログラミング言語ではなく、「同期」という言葉に言及しています。Java では、さまざまなコンテキストで同期化されたという言葉は、暗黙的な監視/ロックを意味し、ロックが多すぎるとパフォーマンスが低下する可能性があります。きめ細かいロックまたはノンブロッキング アルゴリズム/ CAS戦略がパフォーマンスを向上させるユースケースがあります。トピックは非常に広いため、より具体的にする必要があります。

編集:あなたが説明したシナリオでは、すべての作業が完全にシリアルであり、すべての状態が共有されている場合、マルチスレッドの実装にはほとんどまたはまったくメリットがありません。ただし、このような極端な例はまれであり、多くの場合、タスクの一部を並行して実行すると、パフォーマンスが大幅に向上します。アムダールの法則を使用して、タスクを並列化しようとするときの理論上の最大パフォーマンスの利点を見つけることができます。

編集:

あなたの編集に関して、たまたまSpring Batchを使用したことがあるので、スレッドプールを使用してリストからアイテムを読み取る場合は、同期を使用する必要があり、多くの方法でそれを行うことができることを確認できます。それらのうちの2つ:

public class NextReader implements ItemReader<String> {
    private List<String> itemList;
    private AtomicInteger current = new AtomicInteger(0);

    public NextReader(ListBean listBean) {
        itemList = listBean.getItemList();
    }

    public syncronized String read() {
        int index = this.current.getAndIncrement();
        if (index < itemList.size()) {
            return itemList.get(index);
        } else
            return null;
    }   
}

また

public class NextReader implements ItemReader<String> {
    private List<String> itemList;
    private AtomicInteger current = new AtomicInteger(0);

    public NextReader(ListBean listBean) {
        itemList = listBean.getItemList();
    }

    public syncronized String read() {
        int index = this.current.getAndIncrement();
        if (index < itemList.size()) {
            return itemList.get(index);
        } else
            return null;
    }   
}

どちらも同じ効果があります。つまり、スレッドセーフな方法で複数を使用して itemList から読み取ることができます。

于 2013-06-10T13:22:50.347 に答える
0

全体の処理が同期されていれば、スレッド数に関係なく同じ時間がかかるというのは正しいです(実際には、コンテキスト切り替えなどのオーバーヘッドにより、スレッド数が多いほど時間がかかります)。 .

このような場合の手がかりは、プロセスメソッド全体を同期しないことです。理想的には、1 つのメッセージの処理が別のメッセージの処理とは完全に独立している必要があります。その場合、理論上は 1000 個のメッセージを同時に処理でき、1000 個のプロセッサを自由に使用できる場合、1000 分の 1 の時間で済みます。

実際には、その中間のどこかになります。それぞれが互いに独立したコードとデータをカバーする多数の小さなロックを使用する場合があります。または、各メッセージのすべてのデータを互いに独立して保持し、その部分の同期を必要としない場合がありますが、主な処理が完了すると、結果を共有配列に挿入する必要があります。共有配列へのアクセスをロックする必要があります。配列。

于 2013-06-10T13:15:40.000 に答える