Linux10:マルチスレッドプログラミング(スレッドとプロセスの違い、基本的なスレッド機能、スレッド通信、同期、相互除外)

マルチスレッドプログラミング(スレッドとプロセスの違い、基本的なスレッド機能、スレッド通信、同期、相互除外)

1.スレッドとプロセス:

プロセス:
システムでのプログラム実行とリソース割り当ての基本単位
(データセグメント、コードセグメント、スタックセグメント)

スレッド:
アプリケーションが複数のタスクを同時に実行できるようにしますメカニズム
(軽量プロセス、基本スケジューリングユニット内のプロセス)
複数の実行パスが同時プロセスメモリスペースを共有し、共有リソースプロセス:
プログラムコード
セグメントの実行
初期化データセグメント
はデータセグメントの初期化
ヒープスペース
スタックスペース(独立)
ファイル記述子
pthread
呼ばれるposixスレッドインターフェイスに従って、ヘッダーpthread.hファイルが必要です。リンクlibpthread.apthread
はLinuxシステムのライブラリではありません

プロセス->スレッド:
linux2.2カーネルフォークは軽いプロセスを作成し、最大4096、2.4カーネルは数の制限を排除します

スレッドとプロセスの違い:
プロセスには独立したアドレススペースがあり、スレッドには個別のアドレススペースがありません。(同じプロセス内のスレッドは、プロセスのアドレススペースを共有します)

スレッドを導入する理由:

プロセスを開始するために費やされた空間は(30倍程度)スレッドを開始するために費やされた空間よりもはるかに大きく、スレッド間でスイッチするのに必要な時間ははるかに少ないプロセス間でスイッチするのに必要な時間よりも長い(> 10倍)
メンテナンスプロセスはスレッドよりもはるかに多くのカーネルを消費します------プロセステーブル
データをスレッド間で共有できるため、通信が容易になります

プロセスVSスレッド:

ここに写真の説明を挿入

スレッドとプロセスの選択方法:

1)頻繁に作成および破棄する
必要がある優先スレッド2)多くの計算必要とする優先スレッド
切り替えに時間と手間がかかり、計算効率に影響することを考慮してください
。3)関連性の高い処理スレッド、関連性の低い処理プロセス
4)次のように拡張できます。マルチマシン配布にはプロセスを使用し、マルチコア配布にはスレッドを使用します
。5)すべての要件が満たされたら、最もよく知っていて、最も得意な方法を使用します。

2.スレッドの基本機能:

2.1:スレッドの作成:

作成:

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

Restrictは、C99標準で導入されました。これは、ポインターを制限および制約するためにのみ使用でき、ポインターがデータオブジェクトにアクセスする唯一の最初の方法であることを示します。つまり、ポインターが指すメモリの内容を変更するすべての操作がポインタを介して変更する必要がありますが、他の手段(他の変数またはポインタ)を介して変更することはできません。これの利点は、コンパイラがコードをより適切に最適化し、より効率的なアセンブリコードを生成するのに役立つことです。int* restrictなどptr、ptrが指すメモリユニットはptrのみがアクセスでき、このメモリユニットを指す他のポインタは未定義であり、鈍いポイントは無効なポインタです。制限の出現は、C言語に固有の欠陥によるものです。Cプログラマーはこの欠陥を積極的に回避する必要があり、コンパイラーも非常に協力してコードを最適化します。
パラメーター:

スレッドID // unsigned long(pthread_t)

スレッド属性:// NULL

属性を結合:
結合
固定カーネルスレッドへのユーザスレッドを、CPUのタイムスライスのスケジューリングは(つまり、軽量プロセスである)、結合属性を持つスレッドが必要なときに常に1があることを保証することができ、カーネルスレッドですカーネルスレッドはそれに対応します。
バインドされていません。
ユーザースレッドとカーネルスレッド関係は常に固定されているわけではありません。システムが割り当てを制御します。

分離属性:
スレッドがそれ自体を終了する方法を決定するために使用されます。
分離。
スレッドが終了すると、占有していたシステムリソースがすぐに解放されます。
非分離
。スレッドによって占有されているシステムリソースは解放されません。つまり、実際の終了はありません。pthread_join()関数が戻った場合にのみ、作成されたスレッドは独自のシステムリソースを解放できます。

スレッドエントリ関数:スレッドエントリ関数に
渡されるパラメータ

戻り値:
成功した場合は0を返し、失敗した場合はエラーコードを返します

2.2:スレッドの識別:

thread_t pthread_self(void);
スレッドIDを取得
unsigned long int- %lu

2.3:スレッドの出口:

void pthread_exit(void * value_ptr);
スレッド終了
正常終了
異常終了
パラメータ:
スレッド終了の状態を保存します

2.4:スレッド待機(接続):

int pthread_join(pthread_t thread、void ** value_ptr);
指定されたスレッドが終了するのを待ちます
パラメータ
待機するスレッドID
は、スレッド終了の状態保存します。通常
、pthread_exitの値受け取るか、返すにはNULLを指定します。

2.6:スレッドのキャンセル:

int pthread_cancel(pthread_t thread);
不足していないスレッドをキャンセルします

2.7:スレッド属性:

初期化:
int pthread_attr_init(pthread_attr_t * attr);
attr:スレッド属性の
成功:0エラー:-1
バインディングプロパティを設定します。
int pthread_attr_setscope(pthread_attr_t * attr、int scope);
PTHREAD_SCOPE_SYSTEM:バインドされた
PTHREAD_SCOPE_PROCESS:バインドされていない
成功:0エラー:-1
スレッド分離プロパティを設定します。
int pthread_attr_setdetachstate(pthread_attr_t * attr、int detachstate);
PTHREAD_CREATE_DETACHED:切り離された
PTHREAD _CREATE_JOINABLE:切り離されていない
成功:0エラー:-1

2.8:スレッドのクリーニング:

リソースリリース:

 void pthread_cleanup_push(void (*routine)(void*), void *arg);
  void pthread_cleanup_pop(int execute);

パラメータ:

ルーチン:クリーンアップを登録する関数のポインター
引数:クリーンアップ関数に渡されるパラメーター
実行:クリーンアップ関数が
0と呼ばれるかどうかを決定します-0
以外は呼ばれません

注意:first-in-last-outスタック構造管理を採用し、2つの関数間のプログラムセグメントでの終了アクション(pthread_exit()の呼び出しと異常終了(他のプロセスはpthread_cancelを使用して現在のプロセスをキャンセルする)を含む)が戻りなしで実行されます

3:スレッド間の通信:

1.プロセスリソースを直接共有する(グローバル変数を使用)
2。シグナル(同じプロセス):
pthread_kill(); -------- kill

4:同期と相互排除:

4.1:同期と相互除外を行う理由:

リソースの保護と独占を実現する

4.2:同期および相互に排他的な操作:

4.2.1:相互に排他的なセマフォ(シグナルロック):

必要なライブラリをインストールします。

apt-get install manpages-posix-dev

意味:
ミューテックスロックは、ある意味でグローバル変数と見なされます。
リソースが操作されるたびに、デフォルトでロックが検出されます。ロックがロック状態の
場合は、ロックがロック解除されるのを待ちます。ロックがロック解除状態の場合は、ロックが使用されます。使用後、ロックを解除します。
カテゴリ:
高速ミューテックスロック
上記の意味に沿って最も一般的に使用されるロック、
検出
ロック、高速ミューテックスロックの非ブロッキングバージョン、
再帰ロック、
複数ロック、
使用プロセス:

ミューテックスの初期化:pthread_mutex_init
ミューテックスロック:pthread_mutex_lock
ミューテックス判断ロック:pthread_mutex_trylock
ミューテックスロック解除:pthread_mutex_unlock
除去ミューテックスロック:pthread_mutex_destroy

相互除外ロックAPI:
作成:
動的作成:
pthread_mutex_init
パラメーター1:ロックを記述する変数pthread_mutex_t mutex;

パラメータ2:ロックタイプを指定します。
デフォルトのNULLは、高速ミューテックスを作成することを意味します
PTHREAD_MUTEX_INITIALIZER:高速ミューテックス
関数の入力値を作成しますMutexattr PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP:再帰ミューテックスを
作成しますPTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP:エラー検出ミューテックスを作成します

静的に作成:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//静态创建快速互斥锁

Lock
int pthread_mutex_lock(pthread_mutex_t * mutex); //ロックに成功した場合は、
int pthread_mutex_trylock(pthread_mutex_t * mutex);を待ちます。
ロックに成功した場合は、失敗するとエラーが返されます。非ブロック
ロック解除
int pthread_mutex_unlock(pthread_mutex_t * mutex);
ロックを破棄します
int pthread_mutex_destroy(pthread_mutex_t * mutex);
軽微な欠陥
デッドロックに注意してください:同じスレッドでは、最初のロックは問題なく、次にロック解除はありません。その後、再度ロックすると、ブロックされ、永久にブロックされます。

4.2.2:条件変数:

意味:
条件が満たされない場合、プログラムはブロックされ、条件が満たされた場合、条件のブロックを解除できます。
関連API:
作成:
静的モード

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

動的な方法

int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
  没有满足条件阻塞
int pthread_cond_wait(pthread_cond_t *restrict cond,
              pthread_mutex_t *restrict mutex);
 满足条件解除阻塞
int pthread_cond_signal(pthread_cond_t *cond);

破壊

  int pthread_cond_destroy(pthread_cond_t *cond);

4.2.3:セマフォ(信号灯):

意味:
プロセス内の信号とは異なるスレッドのセマフォは、
基本的に非負の整数カウンターであり、共通リソースへのアクセスを制御するために使用されます。
原則:
P操作はsemを1つ減らし、V操作はsemを1つ増やします。セマフォsemの値がゼロ以上の場合、プロセス(またはスレッド)はパブリックリソース(相互に排他的な同期
セマフォ関連API)にアクセスでき
ます。

int sem_init(sem_t *sem, int pshared, unsigned int value);

セマフォsemを作成します。初期値は値pshared:0として指定
pshared:セマフォを複数のプロセス間で共有できるかどうかを決定します。Linuxはプロセス間でのセマフォの共有をまだ実装していないため、この値は、セマフォ値取得するために0と見なすことができ
ます。

int sem_getvalue(sem_t *sem, int *sval);

コスト-1:

 int sem_wait(sem_t *sem);---阻塞
 int sem_trywait(sem_t *sem);--非阻塞
 释放 +1:
 int sem_post(sem_t *sem);

掃除:

 sem_destroy(sem_t *sem);

予防:

同期と相互除外を使用する場合、すべてのスレッドはこの操作に従う必要があります。そうでない場合は意味がありません。

おすすめ

転載: blog.csdn.net/weixin_40734514/article/details/109254157
おすすめ