マルチスレッド | スレッド同期とスレッド セーフ

1.マルチスレッド

スレッドには、それに関連する関数ライブラリ呼び出しの完全なセットがあり、その関数名のほとんどはpthread_で始まります。これらのライブラリ呼び出しを使用するには、マクロ_REENTRANTを定義し、ヘッダー ファイル pthread.h をプログラムにインクルードし、プログラムのコンパイル時にオプション-lpthreadを使用してスレッド ライブラリをリンクする必要があります。

-L はライブラリの保存場所を指定します。

-l はライブラリの名前を指定します

並列: 特殊な同時操作、同期操作、複数のプロセッサーが必要

同時実行性: 一定期間にわたって交互に実行することで、単一のプロセッサで次のことが可能です。

注: 複数のプロセッサを使用することは、必ずしも並列または同時であるとは限りません。

 

2. スレッドの同期

プロセス内のすべてのスレッドは、同じアドレス空間と、開いているファイルなどの他のリソースを共有します。1 つのスレッドによるリソースの変更は、同じプロセス内の他のスレッドの環境に影響を与えます。したがって、さまざまなスレッドのアクティビティは、互いに干渉したりデータ構造を破壊したりしないように同期する必要があります。たとえば、2 つのスレッドが同時に二重リンク リストに要素を追加しようとすると、要素が失われるか、リンク リスト構造が破壊される可能性があります。

スレッドの同期とは、スレッドが特定の重要なリソースで動作しているとき、他のスレッドはそのリソースで動作できないことを意味します。スレッドが動作を完了するまで、他のスレッドは動作できます。つまり、調整されたペースで、スレッドがあらかじめ決められた速度で動作できるようになります。順番に実行します。スレッド同期には、ミューテックス ロック、セマフォ、条件変数、読み取り/書き込みロックの 4 つの方法があります。

2.1 ミューテックスロック

int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t 
*attr);//attr:锁的属性,不需要传空即可
int pthread_mutex_lock(pthread_mutex_t *mutex);//加锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁锁
//注意,互斥锁mutex都需要传地址,因为要改变它;

2.2信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);
//信号量的初始化
//sem_init()在sem指向的地址初始化未命名的信号量。这个value参数指定信号量的
初始值(第三个参数)。
//pshared:设置信号量是否在进程间共享,Linux不支持,一般给0; (非0为共享)
int sem_wait(sem_t *sem);
//P操作,wait表示等待,相当于是等待获取资源,那么就是P操作
int sem_post(sem_t *sem);
//V操作
int sem_destroy(sem_t *sem);
//销毁信号

2.3 条件変数

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t
*attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t
*mutex);
//将条件变量添加到等待队列中,阻塞,等待被唤醒;第一个参数是条件变量的地址,第二个参
数是互斥锁;
//也就是说条件变量往往伴随着互斥锁的使用;
int pthread_cond_signal(pthread_cond_t *cond); //唤醒单个线程
int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒所有等待的
线程
int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件变量

2.4 読み取り/書き込みロック

リーダーとリーダーはリソースを共有し、リーダーとライターは相互に排他的であり、ライターとライターは相互に排他的であり、ライターとリーダーは相互に排他的です。

#include <pthread.h>
int pthread_rwlock_init(pthread_rwlock_t
*rwlock,pthread_rwlockattr_t *attr);
//第一个参数是锁的地址,第二个参数是锁的属性
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//加读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//加写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁,不管加的
是读锁还是写锁,都用unlock解锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁

3. スレッドセーフ(ポイント)

スレッド セーフとは、複数のスレッドが実行されている場合、スレッドのスケジュール順序に関係なく、最終結果が同じで正しいことを意味します。そうすると、これらのスレッドは安全であると言われます。

スレッドの安全性を確保するには、次のことを行う必要があります。

1) スレッド同期により、重要なリソースに同時にアクセスできるスレッドは 1 つだけになります。

2) マルチスレッドでスレッドセーフ関数 (リエントラント関数) を使用する いわゆるスレッドセーフ関数とは、次のことを指します: 関数が競合状態なしに複数のスレッドから同時に呼び出せる場合、それを関数と呼びます。スレッドも安全です。

一般的に言えば、_r が付いている関数のバージョンは、その関数のリエントラント バージョンです。

リエントラント関数: リエントランシーとは、繰り返しエントリすることを意味します。第一に、それはこの関数が中断できることを意味します。第二に、それは独自のスタック上の変数を使用することを除いて、どの環境 (静的も含む) に依存しないことを意味します。そのような関数は純粋なコードです(純粋なコード) は再入可能であり、別々のスタックを使用するため、関数の複数のコピーが互いに干渉することなく実行できます。本当にグローバル変数 (静的変数を含む) にアクセスする必要がある場合は、必ず相互排他を実装してください。リエントラント関数は並列実行環境では非常に重要ですが、一般にグローバル変数にアクセスするとパフォーマンスが低下します。

注: マルチスレッドでは、スレッドがグローバル (静的) 変数を使用する場合は注意してください。すべてのスレッドがこれらの変数を共有し、スレッドが独自のローカル変数を使用することが最善であるためです。

スレッドにも ID があります (Linux にはスレッドを実装する独自の方法があります。カーネルにはマルチスレッドの概念がなく、スレッドをプロセスとして扱います。メイン スレッドの PID はプロセス PID で、他のスレッドは PID+1 です)。

表示方法: ps -eLf

おすすめ

転載: blog.csdn.net/weixin_53472334/article/details/132327893