マルチスレッドプログラミングとロック


  複数のプロセス、互いの各プロセス独立して、メインプログラムの安定性に影響を与えない、子プロセスがクラッシュは問題ではありません。CPUを増やすことで、それは簡単にパフォーマンスを拡張することができ、スレッドのロック/アンロックの影響を最小化し、大幅にパフォーマンスを向上させることができ、スレッドを実行するアルゴリズムモジュールであっても、低効率は問題ではありません。それぞれの子は、相互作用に非常に大きな、しかし、複雑なロジック制御の上限の全体的なパフォーマンス、およびメインプログラムのニーズを達成するために、2GBのアドレス空間と関連するリソースを持っている、プロセス境界を越えて必要な、データ転送量が多い場合は、ではないデータ転送の少量のための良好なので、計算集約型マルチプロセススケジューリングは、オーバーヘッドが比較的大きいので、我々は、マルチスレッドを使用することができます。

まず、マルチスレッドの長所と短所

利点:

1)それは非常に「質素な」マルチタスク動作モードがあります。Linuxシステムでは、新しいプロセスは、その別のアドレス空間に割り当てなければならない開始、そのコードセグメント、スタックとデータセグメントを保持するデータテーブルの多数の確立は、これは「高価な」マルチタスク作業です。互いの間で同じアドレス空間を使用して、プロセス内で複数のスレッド上で実行されているが、シェアのほとんどのデータが、スレッドのスペースを開始し、それははるかに少ない、それがプロセス空間を開始するのにかかるよりもかかる、と、お互いにスレッドを切り替えます所要時間は、時間がプロセス間で切り替えるために必要とされるよりもはるかに少ないです。もちろん、特定のシステム上で、このデータは、より大きな差を有していてもよく;
2)スレッド間通信機構を容易に、同一のデータ空間を共有するプロセスの間に糸ので、一つのスレッドのデータをそのまま他のスレッドによって使用されてもよいですこれだけでなく、高速でなく、便利である;
3)より効率的なマルチCPUシステム。オペレーティングシステムは、スレッドの数が異なるCPU上で異なるスレッドを実行して、CPUの数よりも大きくないことを保証する場合、
4)プログラムの構造を改善します。長く複雑なプロセスが実行のいくつかの独立または半独立部分に複数のスレッドに分割すると考えることができ、そのようなプログラムは理解し変更するために有益であろう。

短所:

1)各メインスレッド共通のアドレス空間、アドレス空間が2 GBに制限されている;
2)とスレッドロック制御煩雑との間の同期、
クラッシュ3)スレッドは、プロセス全体の安定性に影響を及ぼし得る;
4)パフォーマンスを向上させることができないCPUを増やし、その後も、スレッド数がある程度に達した後、
スレッドのスケジューリング自体が面倒なことになった後、スレッドよりも制限5)のスレッドが全体のパフォーマンスを向上させることができ、そして、あなたはより多くのCPUを消費する必要があります

次に、我々は、使用スレッドに固有の概念とシンプルを理解するために来ます。

第二に、浅い知識のスレッド

1.スレッドモデル

同じプロセス空間内のスレッドで作業し、先に述べたように、子スレッドと共有リソースのメインスレッドは、彼のモデルがあるようです

ここに画像を挿入説明
)(主な機能は、息子、スレッドメインスレッドメインスレッドと呼ばれ、複数のサブスレッドを作成することができます彼らは創造に渡されたとき、彼らは、このスレッドの勝者を必要とするパラメータの作業を行い、どのような特定のタスクがスレッドの仕事の間に別のタスクがあり、かつ、
スレッドは、そのようなファイルでマルチコア環境として、アプリケーションの処理を向上させることができますI / O性能特性やソケットI / Oなどが目詰まりを生成します。Unixシステムでは、実行可能なプログラムと、そのようなファイルディスクリプタのアドレス空間などの他のリソースのホストを含め多くのことを、含むプロセス。多くの場合、完全に関連するタスクに異なるコード間では、データを交換する必要があります。マルチプロセス方式ならば、それはスレッドよりも大きいスライスのにかかる時間を作成するプロセスは、別のプロセス間通信は、あまりにも面倒、ユーザ空間とカーネル空間での頻繁な切り替えの必要性、大きなオーバーヘッドがあります。あなたが共有グローバル変数を使用することができますので、スレッド間の通信(データ交換)は非常に効率的になるように、しかし、あなたは、マルチスレッドのアプローチを使用している場合。

プロパティと機能をスレッド2

pthread_attr_t

スレッドを作成する前に、我々が定義する必要があるのpthread_attr_tの構造の種類を、
次のように構造体のメンバーは以下のとおりです。


typedef struct
{
        int detachstate; 线程的分离状态  
        int schedpolicy; 线程调度策略
        struct sched_param schedparam; 线程的调度参数
        int inheritsched; 线程的继承性
        int scope; 线程的作用域
        size_t guardsize; 线程栈末尾的警戒缓冲区大小
        int stackaddr_set;
        void * stackaddr; 线程栈的位置
        size_t stacksize; 线程栈的大小
}pthread_attr_t;

スレッド属性構造メンバ参照のブログ:マルチスレッド財産pthread_attrコメント

 最初にリストの構造体のメンバとしてdetachstateそれを追加する必要がある(1つの分析と呼ばれる関数)。

  プロセスが作成されたら、それは最初にデフォルトのスレッドを作成し、通常このスレッドがあると呼ばれるメインスレッド(またはコントロールのスレッド)、C / C ++プログラムは、メインスレッドはスレッドへの主な機能を介して行われ、メインスレッドの呼び出しは、pthread_createの( )スレッドの作成が子スレッドと呼ばれ、子スレッドは、作成時にユーザによって指定された独自のエントランス機能を持つことができます。各スレッドは、独自のスレッドIDを持っている、あなたはpthread_selfで関数を得ることができます()。メインスレッドに加えて、最も一般的なスレッドモデルは、一度作成した特別な、他のスレッドであり、ピア関係で、暗黙の階層関係は、互いの間に存在しません。プロセスごとのスレッドの最大数は、窓やPOSIXの両方を作成することができ、メインスレッドと子スレッド間のデフォルトの関係は、特定のインプリメンテーションの決定によって決定されます。子スレッドが終了したか否かを、メインスレッドが完了出口一度、すべてのサブスレッドの実行終了します。そして、全体のプロセスが終了または死者は、スレッドの終了ステータスの実行の部分を維持するが、まだ破壊されていない、とプロセスがそのスレッドのすべての破壊後に破壊されなければならない、そしてプロセスは死んだ状態になっています。スレッド機能は、出口は、終了またはそうでなければ非常に、状態にスレッドを終了完了するが、スレッド・システム・リソースの割り当てのために
システムを再起動する前に、ソースが必ずしも解放されていない、おそらく、スレッドとして依然として、スレッドの終了状態を解除することができませんでしたエンティティは、オペレーティングシステム内に存在し、破壊された場合に、スレッド属性に応じ。この場合、メインスレッドと子スレッドは、通常、次の2人の関係が定義されています。

  1. (合流可能)に参加することができます:この関係では、メインスレッドは、オペレーションの明確な実装を待つために子スレッドの後、実行待ちの操作のメインスレッドは、子スレッドを終了し、メインスレッドに参加し、後に業務を継続するためにメインスレッドを待つ必要があります次のステップ。メインスレッドは、子スレッドがランデブーすることができます満たしていなければなりません。メインスレッドの待機スレッド関数の呼び出しでは内部関数オブジェクトは、子スレッドも操作が実行されなければなら参加し、終了状態に、メインスレッドの前に終了させることができる場合でも、サブスレッドを達成するために、そうでない場合、システムはに割り当てられたスレッドを破壊するためのイニシアチブを取ることはありませんシステムリソースのスレッドがリリースすることは決してありません。
  1. 相分離(剥離):子スレッドを表しており、子スレッドが状態に、このアプローチは、より一般的にスレッドの数の場合に使用されると終了し、時にはメインスレッドをできるように、この場合には、相分離がメインスレッドを、参加する必要はありません。それぞれの子の子のためのスレッドが待機、またはメイクの手配の終わりまでに1シーケンスの終了を待つためにメインスレッドをスレッド、それはとても多くのサブスレッドの例によって複雑で、困難または不可能である、このアプローチは頻繁に使用されます。自体を終了させるためにどのように決定するスレッドのスレッド状態を分離する、デフォルトの場合には、スレッドが非絶縁状態であり、この場合には、スレッドの終了のために元のスレッド待ちのみときpthread_joinを関数が返す作成され、作成されたスレッドは独自のリリースのシステムリソースを占有終了したとみなされ、スレッドは自分の終わりを実行するために待機している他のスレッドから分離されていない、すぐに中止し、システムリソースを解放するスレッド。

  必要に応じて、これらの特性のために、我々は、スレッドの別々の状態を設定する必要があり、また、各スレッドのスタックサイズを変更する必要があります。各スレッドは、デフォルト状態を作成するために結合可能であるした後、この状態はそれを呼び出すために、メインスレッドがpthread_joinを待ち、最後にそれ以外の場合は子スレッドを終了する必要があり、メモリリソースは、メモリリークが発生解放することはできません。したがって、一般的なスレッドが別の状態として提供され、我々はスレッドを作成する2つの特定の方法があります。

  1. 内部のスレッドがこの方法では、最も簡単です(pthread_self())を呼び出し、pthread_detachの
  2. にスレッドを作成するには、プロパティ設定で設定PTHREAD_CREATE_DETACHEDプロパティ
pthread_attr_init()
#include <pthread.h>

int pthread_attr_init(pthread_attr_t *attr);   //初始化线程对象的属性;
int pthread_attr_destroy(pthread_attr_t *attr);   //销毁一个目标结构,并且使它在重新初始化之前不能重新使用。

スレッド属性構造が定義されている唯一のパラメータ、成功時に0を返し、0以外のエラー番号を返すために失敗。

pthread_attr_setstacksize()
#include <pthread.h>

int pthread_attr_setstacksize(pthread_attr_t *attr,size_t stacksize); 

0戻り成功、非ゼロを返すことに失敗し、最初のパラメータは、第二のスレッドスタックのサイズであり、スレッド構造の特性です。

pthread_attr_setdetachstate()
#include <pthread.h>

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

取る、スレッドが分離されて設定するか、参加PTHREAD_CREATE_DETACHEDを、他者、自己破壊を待つメモリ領域を解放することなく、スレッドの実装後にするとき、
取るPTHREAD_CREATE_JOINABLEを、メインスレッドが呼び出す必要がpthread_joinを()我々は彼に反対しているので、出口までの子スレッドを待機する機能を出口の状態に興味、メインスレッドがこのサブスレッドの終了を知っている、関数リターンでブロックされ、スレッドがスペースを解放、破棄されます。
成功時には0を返し、ゼロ以外を返すために失敗。

pthread_create();
#include <stdio.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine) (void *), void *arg);

最初の引数は、スレッドIDを返すために使用されるスレッド識別子へのポインタである。
第二のパラメータは、スレッドの属性を設定するために使用され、
3番目のパラメータは、関数を実行するスレッドの開始アドレスである、すなわち、タスク機能によって必要とされます;
最後のパラメータは、関数を実行するためのパラメータです。

第三に、ロック

  リソースが異なるスレッドを変更するためにアクセスされている場合、私たちは、このリソースが呼び出される入れ、重要なリソースは、関連するコードを変更するためのリソースへのアクセスが呼び出され、重要な地域それでは、どのようにマルチスレッドプログラミング、複数のスレッド間で共有同じ共有リソースを解決するために考慮すべき問題です。

私たちは、変数の値で頻繁に使用プロセスにスレッドAの必要性が、この時、何かをやっている、スレッドBもこの値を使用しているとし、変数の値を変更し、各スレッドA時間は、同じではありません取得し、この重要なリソースの値は、スレッドAの作業をリードする、適切に実行することはできません!
この時点で、私たちは、ロックを使用する必要があります。

ブロッキング・ロック

複数のスレッドがすべてのスレッドがに対処するためにキューイングされ、同じ時間に同じメソッドを呼び出します。運転に入った、競争によって準備ができて、すべてのスレッドを用意し、彼らは準備ができて、スレッド準備に入ることができる前に、対応する信号(ウェイクアップ時間)を取得する際に、待ちにブロックされた状態にスレッドをしてみましょう。

ノンブロッキングロック

同時に複数のスレッドロックを獲得する最初のスレッドの一つが、その後、他のスレッドの裁判官が直接返し、その後、ロックを取得していない、と最初のスレッドが取得するためのロックを解除した場合にのみとき、メソッドを呼び出して、他のスレッドができで、それが解放される前に、他のスレッドが失敗を取得します。

スピンとミューテックスロック

スレッドがロックを取得するときにロックが他のスレッドによって取得された場合、ロックが取得されるまで、そのスレッドは、サイクルを待ち、その後ロックが正常に取得されているかどうかを決定していき、ループを終了します。ロックの取得スレッドがループしながら、呼び出されたとして、活動しているが、効果的に任意のタスクを実行していなかった、このロックの使用がビジー待ちが発生します。
また、同期の共有リソースを保護するために、ミューテックスは、いつでも、多くても1つのホルダーで、それは言った、唯一のロックを取得する任意の時点で最大1つの実行単位で持つことができます。しかし、わずかに異なる2つのスケジューリングメカニズム。リソースが既に占有されている場合、ミューテックスの場合は、リソース要求はスリープ状態に入ることができます。スピンロックが別の実行ユニットを開催されている場合でも、睡眠への発信者を引き起こすことなく、スピンロックは、呼び出し側がスピンサイクルロックホルダがロックをリリースしているかどうかを確認することでした。

デッドロック

複数のスレッドが複数のオブジェクトと呼ばれていた場合はロックされたとき、それは「デッドロック」であってもよいです。例えば:A、同時に2つの共有変数を使用してB 2つのスレッドがMおよびN、それぞれが独自の対応するロック変数MおよびNを有します 最初のスレッドロックアクセスM mを取得するための時間は、その後、彼は、ロック変数N-Nへのアクセスを取得する必要がある。ケースBのスレッドを引き起こし、N Mは、ロックを保持しているロック・スレッドを待っている場合は、「デッドロック」。
ここに画像を挿入説明

四つ必要デッドロックの条件
1、相互に排他的:リソースは、アクセスする唯一のプロセスを可能にするが、リソースがプロセスに割り当てられると、他のプロセスがプロセス・アクセス・ノードまでもはやアクセスでき
ビーム。
2、所持及び待機:プロセス自体がリソース(一つ以上)を取るだけでなく、リソースが満たされていない、リソースを解放するために他のプロセスを待っています。
3は、押収することはできません。他の誰かがリソースの所有権を持っている、あなたは彼らが他の人のリソースに移動するためのリソースを必要とすることはできませんので、それを引き継ぎます。
図4に示すように、円形のウェイトは:プロセスチェーンは、各プロセスが次の処理のために必要なリソースの少なくとも一つを果たしているように、存在します。
上記4つの条件が満たされた場合には、間違いなくデッドロックにつながる、プロセスのデッドロックは、彼らが開催されたリソースを解放することはできません、上に行くことはできません。これは、CPUのスループットが発生します。だから、デッドロック状態は、システムリソースの浪費であり、コンピュータのパフォーマンスに影響を与えます。そのため、デッドロックの問題を解決するためには非常に必要でアップしています。
デッドロックは、4つの条件が必要となる限り、4つの条件のうち少なくとも一つの条件があるとして満たされていない、そして、それは不可能デッドロックが発生しています。条件が共有リソースに必要な非排他的であることから、だけではなく、変更することはできません、それはまた、デッドロックの損傷のため、他の三つの主要な条件ので、保証されなければなりません。

A、「所有して待つ」破壊条件
1:すべてのプロセスの実行を開始する前に、あなたが必要としている全体の実行ですべてのリソース一度適用する必要があります。
利点:実装が容易かつ安全。短所:リソースが満たされていないので他の人が深刻で、その結果、リソースの使用率を減らし、資源を利用することはありません満たされているが、このプロセスは、開始することができない
リソースの無駄。頻繁にプロセスの飢餓。
方法2:このメソッドは、改良の第一の方法で、プロセスだけ早い動作に必要なリソースへのアクセスを許可されている、彼らは実行を開始、運転中に徐々に解放されたリソースの割り当ては、新しい要求に行くまで使用されていました資源。この場合、リソース使用率は、飢餓削減プロセスの問題も改善されます。
B、破壊条件「を押収することはできません」
プロセスは、すでにいくつかのリソースを保持している場合、開催されている、必要なときに、後で使用するために、次に再適用提案された新しいリソース要求が満たされていないで、それはすべてのリソースを解放する必要があります。プロセスは、リソースの所有権を持っていることを、この手段が簡単にリリースされますか押収さ。この方法は、実装がより複雑になり、コストが比較的大きいです。リリースリソースが前に開催された可能性が高いそれが唯一のターンアラウンドのプロセスを長引かないだろう、非常遅れている実装プロセスにつながるなどの効果的な作業プロセス、繰り返しアプリケーションとリソースの解放につながることですが、また、システムのスループットに影響を与えてきました。
C、破壊「待機ループ」条件が
線形配列定義のリソースタイプによって防止することができるプロセスがリソース番号iを占有する場合、各リソースは、アプリケーションリソースのみであること、その後次回番号付けされてもよい
私より数の大きいを適用することを資源。

リリース8元の記事 ウォン称賛11 ビュー302

おすすめ

転載: blog.csdn.net/weixin_45121946/article/details/104605316