同時プログラミング-探索1


0 x 01コンカレントとは
コンカレントの優先順位を理解するには、コンカレントとパラレルの概念を区別します.
同時:一定期間に複数のアクションが存在することを示します.パラレル:同じ時点で複数のアクションが同時に存在することを示します.
例えば、今ブログを書いていますが、立ち止まって食べ物(パイナップルスライス)を食べてから書く、食べると書いています.この2つの動作はしばらくの間発生しており,これは同時と理解できる.一方、私はこのブログを書くと同時に音楽を聴いています.では同時に存在する2つの動作(ブログを書いたり、音楽を聴いたり)が同時に発生しているのが並列です.
上記の2つの概念から,並列動作が含まれていることが明らかになった.したがって、我々が一般的に言う同時プログラミングは、cpuにとって同時実行であり、交互に実行されている可能性がある.
ここまで言うと、なぜ同時プログラミングが必要なのかと聞かれるかもしれません.単一の問題を解くとき,複数の実行プロセスに関連するプログラミングモードを並列プログラミングと呼ぶ.
0 x 02同時実行が必要な理由
  • ハードウェアの発展はソフトウェアの進度を推進し、マルチコア時代の到来
  • アプリケーションシステムのパフォーマンスとスループットに対する厳しい要求
  • ビッグデータ時代の到来
  • モバイルインターネット、クラウドコンピューティングによるコンピューティングシステムへの衝撃
  • 0 x 03同時プログラミング方式
    Java:マルチプロセス/マルチスレッドの同時実装
    Go:コパス--ユーザ状態実装のマルチスレッド方式(goroutine)
    Javaコンカレントモデル
    Java同時モデルを紹介する前に,システムによるマルチスレッドの実現方法を紹介する.システムはユーザー状態スレッドとカーネル状態スレッドの2つのスレッドの実現方式をサポートし、カーネル状態スレッドはcpuがスケジューリングしない最小単位であるため、これはユーザー状態スレッドとカーネル状態スレッドの間のマッピング関係に関連し、ユーザー状態スレッド:カーネル状態スレッド=1:1、N:1、M:N.
    1:1このマッピング関係はマルチコアの利点を十分に利用しているが,この方式はユーザ状態でスレッド切替を行う過程でカーネル状態スレッド間の切替に関与し,切替オーバーヘッドが大きい.(主にカーネルスレッドの実行時コンテキストの保存と復元に関する)N:1ではマルチコアの利点を十分に利用できないが,ユーザ状態のメモリ切替はカーネルスレッド間の切替に関与しないため,このマッピング関係はスレッド間の切替コストが小さい.M:Nこれは上の2つのマッピング関係の結合体であり,上の2つのマッピング関係の利点を集合しているが,これはスレッド間のこのようなマッピング関係のスケジューリングの複雑さを増大させる.
    Javaの同時プログラミングモードは,1:1というマッピング関係によりスレッド間の同時スケジューリングを実現する.
    Go同時モデル
    Goの同時モードはM:Nという方式で同時スケジューリングを実現する.Goスケジューラには、M(posix thread)、P(スケジューラコンテキスト、一般的にはマシンカーネル数と同じ数に設定されており、マシンの同時性能を十分に発揮できる)、G(goroutine)の3つの重要な構造があります.
    1つのスケジューリングコンテキストは、複数のGoroutine、複数のコンテキストを含むことができるので、すべてのGoroutineをCPUのマルチコア上で同時に実行することができます.Goroutineがスケジューリングコンテキストが見つからないことを発見した場合、global runqueueに配置され、閑散としたスケジューリングコンテキストを待ってスケジューリングされます.スケジューリングコンテキストにマウントされているすべてのGoroutineが実行済みである場合、global runqueueに行ってGoroutineを取得し、この場合取得されていないことに気づいた場合、他のスケジューリングの前にGoroutineを奪い、一般的に一度の奪い取りは、このときにスケジューリングされた上下文の半分のGoroutineを奪い取り、Mを十分に利用してマルチコアスケジューリングされることを確保する.
    0 x 04同時発生の問題
    同時プログラミングによる高性能、高スループットを享受すると同時に、同時プログラミングによる予期せぬ弊害も発生します.
  • リソースの消費量.このような多くのユーザスレッド、カーネルスレッド、ユーザスレッドカーネルスレッド間の切り替えスケジューリングを管理するには、コンテキストなどが、同時プログラミングを参照することによる追加の消費量に起因する.
  • 同時実行中のマルチスレッド間の切り替えスケジューリング、コンテキストの保存リカバリなどは、追加のスレッド切り替えオーバーヘッドをもたらします.
  • 符号化、テストの複雑さ.私たちの生活の例とよく似ていて、3、5人で一緒に活動するのは簡単で、数十、百人以上のチームを連れて活動すると、これらは追加の管理上の費用をもたらします.

  • 本当に陽関があるところには暗いですね.
    これらは私たちが避けられない問題です.同時プログラミングを参照するには、必然的に追加の代価がかかります.しかし、同時プログラミングは、スレッド間の同じリソースへの競合アクセスが、メモリオブジェクトの状態と自分の想像と千差万別になるという無視できない問題をもたらしています.
    Javaスレッドとメモリオブジェクト間のインタラクション
    JAvaスレッドのメモリに対する理解は、スレッドワークメモリ(スレッドごとに固有)、共有メモリもメインメモリ(すべてのスレッドで共有されている)と呼ばれ、javaスレッドがメモリ内のCountオブジェクトを修正する操作です.
    メインスレッドからCountオブジェクトを読み込んでスレッドワークメモリに入れ、その後の読み取り変更はすべてスレッドワークメモリに入れられ、最後に(メインメモリに更新される時間は確定していませんが、store、writeの間に別の操作が挿入される可能性があります)メインメモリに更新されます.上記の操作はすべて順次実行されますが、連続実行は保証されません.
    volatile変数、synchronized同期ブロック
    volatile変数、synchronizedブロックの実行が終了すると、更新するたびに値がすぐにプライマリメモリに書き込まれることが保証されます.volatile変数は多くの人がスレッドが安全だと思っていますが、2つのスレッドが同時に1つのvolatile変数を読み、最後の前と後にメインメモリに更新すると、書き込みが失われることもあるので、volatileはスレッドの安全を保証できません.
    0 x 05同時実戦
    1)スレッドプールの定義
    private static final ExecutorService executor = Executors.newFixedThreadPool(20);

    2)同時サービスの定義
    CompletionService completionService = new 
          ExecutorCompletionService(executor);

    3)同時タスクの発行
    completionService.submit(new Callable() {
        @Override
        public void call() throws Exception {
            return ;
        }
    });

    4)同時結果待ち
    for (int i = 0; i < taskSize; ++i) {
        Future future = completionService.poll(TIME_OUT,
                        TimeUnit.SECONDS);
        Result result = future.get();
    }