どうじせい


この章では、複数のスレッドを同時に迂回する原因、困難と解決方法、テスト方法、問題について説明します.

同期性が必要な理由


同時結合を解消するポリシー:何、いつ切断するか
->大きなサイクルではなく、プロジェクトをいくつかの小さな協力プロジェクトと見なすことができます.
ex)
  • シリーズ:他のシリーズとは関係なく、自分の世界に戻る.
  • 情報収集器:収集中に新しい情報を蓄積し続け、必要な時間を増加させる.
  • 応答時間を向上するために、
  • の複数のユーザを同時に処理する
  • .
  • 情報バッチ分析:応答時間を向上するために複数のコンピュータ間で情報を配信する
  • .

    迷信と誤解


  • 同時性は常にパフォーマンスを向上させます.
    この->は、待機時間が長い場合、または独立して計算するのに十分な場合にのみ一般的ではありません.

  • 同期性が実現しても設計は変わらない.
    何がいつ分かれるかで、システム構造が大きく変わります.

  • WebコンテナまたはEJBコンテナを使用して同期性を理解する必要はありません.
    コンテナの動作方式をどのように処理するかを知り、同時に修正と取り外しを行う.
  • 妥当な考え

  • 同時性は多少負荷を引き起こす.
  • 複雑
  • 同期エラーを再現するのは難しいです.
  • の同期性を実現するには、根本的な設計ポリシーを再考する必要があります.
  • 難関


    2つのスレッドが同じ変数を参照すると、エラーの結果が表示される可能性があります.
    この場合、2つのスレッドが1行のjavaコードを通過するパスの数:12870

    同時性防御の原則


    単一責任原則(SRP)


    オブジェクトを変更するには理由が必要です.同期コードと他のコードを分けます.
    同期コードには独立した開発,変更,協調サイクルがあり,独自の困難があるからである.

    整理:資料範囲の制限

    synchronizedキーワードを使用して、共有オブジェクトを使用するコード内の臨界領域を保護します.
    しかしながら、これらの臨界領域を修正する作業量が大きいほど、これらの臨界領域が正しく保護されているかどうかを判断する努力が必要となるため、共有データをできるだけ低減する:カプセル化

    整理:使用資料のコピー


    最初から共有しない.オブジェクトをコピーし、読み取り専用オブジェクトとして使用します.
    コピーコスト=コピー作成+ゴミ収集<内部ロック

    まとめ:できるだけ独立して実施する


    他のトピックと資料を共有しません.各スレッドはクライアント要求を処理し、情報は非共有ソースから取得され、ローカル変数に格納されます->同期不要

    ライブラリの理解


  • スレッド環境でのセキュリティ・コレクションの使用
  • java.util.同時パッケージ
  • ReentrantLock, Semaphore, CountDownLatch

  • executorフレームワークを使用して、互いに関係のないタスクを実行します.

  • 可能な場合は、スレッドをブロックしない方法を使用します.

  • 一部のクラスライブラリはスレッドに対して安全ではありません
  • 実行モードの理解


    以下は、実行モードの基本英語を説明するためです.
  • 有限リソース:マルチスレッド環境で使用されるリソース.
    -ex.DB接続、長さが限られたリード/ライトバッファ
  • 反発:1回に1つのスレッド/リソース
  • のみを共有
  • 飢餓:スレッドはリソースを永遠に待機します.
  • 死亡:スレッドが互いに終了するのを待つ.
  • LiveRock:フックフェーズスレッド相互干渉
  • 消費者


    生産者トピック:情報を生成します.バッファまたはキューに入れる
    コンシューマトピック:キューから情報を取得して使用
    相手に信号を送る->どちらでもよいが,互いに信号を待つ可能性がある.

    読み取り-書き込み


    スレッドの読み込み:共有リソースの使用
    書き込みスレッド:共有リソースの更新
    ->スループットが重要
    処理率を強調すると、飢餓/更新を許可すると処理率に影響します.

    食事をする哲学者たち



    同時に左を持ち上げると、一生右を持ち上げることができません.
    複数のプロセス競合リソース->デッドライン、ダイナミック、低スループット、低効率

    同期メソッド間の依存性の理解


    メソッド間に依存性がある場合、同期エラーが検出されにくくなります.
    ->共有オブジェクトに対して1つの方法のみを使用する
    複数のメソッドを使用する必要がある場合:
  • クライアントロック
  • サーバで
  • をロック
  • 接続サーバ:ロックを実行する保留ステップを作成します.サーバロックと同様ですが、サーバx
  • は変更されません.

    同期部分を小さくする


    synchronizedを使用してrockを設定できますが、スレッドが遅延し、負荷が増加します.臨界領域の数を減らすためにねじれた臨界領域の大きさも同様である

    正しい終了コードは実現しにくい


    終了コードは、最初から考慮して実装する必要があります.
    ex.
    親スレッドが複数のサブスレッドを作成して終了を待つ場合、サブスレッドは保留されます.
    2つのサブスレッドは、生産者-消費者関係で終了するが、消費者が信号を待つ場合

    テストスレッドコード


    問題を暴露するテストケースの作成->プログラム設定、システム設定、負荷の変換は、一度にスキップすることはできません.

    話にならない失敗を一時のテーマにする


    システムの失敗は使い捨てだと思わないでください.

    マルチスレッドのシーケンスコードを考慮せずに正しく動作し始めましょう


    スレッド環境以外のエラーとスレッド環境内のエラーを分離

    マルチスレッドのコード部分を異なる環境に簡単に埋め込むためのスレッドコードの実装


    スレッド数の変更、実際の環境/テスト環境での実行、異なる速度での戻りと繰り返しのテスト

    マルチスレッドのコード部分を作成し、状況に応じて調整できるようにする


    コードの調整を容易にするスレッド数
    プログラムでスレッド数を変更する方法を検討する
    スループットと効率に応じてスレッド数を自分で調整するコードが必要です

    プロセッサ数より多いスレッドを返す


    スワップを考慮すると、スレッド数はプロセッサ数より大きくなります.

    別のプラットフォームで回転


    異なるプラットフォームでスレッドを処理するポリシーが異なります.

    補助コードをコードに入れて回します。失敗を強要する


    失敗したパスが実行される確率は低い.このような珍しいエラーをより頻繁にしたい場合は、補助コードを追加してコードの実行順序を変更することができます.
  • 直接実施
  • public synchronized String nextUrlOrNull() {
    	if (hasNext()) {
        	String utl = urlGenerator.next();
            Thread.yield();		// 테스트를 위해 추가
            updateHasNext();
            return url;
        }
        return null;
    }
    しかし、この方法には問題がある.
    補助コードの位置決め、関数呼び出しの位置決め、配置コードに補助コードを保持すると、パフォーマンスが低下し、ランダムになります.
    ->テスト環境で補助コードを実行し、実行するたびに設定を変更する必要があります.
  • 自動化
    ツール
  • (AOF、CGIB、ASMなど)の使用
    public class ThreadJigglePoint {
    	public static void jiggle() {
            // 배포할 땐 비워두고 테스트할 땐 무작위로 sleep이나 yield 호출
        }
    }
    
    public synchronized StringnextUrlOrNull() {
    	if (hasNext()) {
        	ThreadJigglePoint.jiggle();
            String url = urlGenerator.next();
            ThreadJigglePoint.jiggle();
            updateHasNext();
            ThreadJigglePoint.jiggle();
            return url;
        }
        return null;
    }
    jiggle:スレッドを毎回異なる順序で実行するには、コードを揺らす必要があります.