Linux -- 条件変数 (条件変数) は、プロデューサー/コンシューマー モデルと読み取り/書き込みロックを実装します。
1. 条件変数
スレッド同期のプロセスでは、次の状況も発生します: スレッド A は、実行を続行する前に、特定の条件が確立されるまで待機する必要があります。条件が確立されていない場合、スレッド A はブロックされます。スレッド B は実行中にこれを使用します。条件が成立すると、スレッド A が起動されて実行を継続します。 Pthread ライブラリの条件変数を使用して、条件の待機をブロックしたり、この条件を待機しているスレッドをウェイクアップしたりできます。条件変数は、pthread_cond_t 型の変数で表されます。
条件変数が静的に割り当てられている場合は、pthread_cond_init を使用して条件変数を初期化し、pthread_cond_destroy を使用して条件変数を破棄し、成功した場合は 0 を返し、失敗した場合はエラー番号を返すこともできます。
条件変数は常にミューテックスとともに使用されます。スレッドは pthread_cond_wait を呼び出してブロックし、条件変数を待機します。
1. ミューテックスを解放します
2. ブロックして待機します
3. スレッドが呼び出すことができます。 pthread_cond_signal 特定の条件変数を待機している別のスレッドを起動するには、pthread_cond_broadcast を呼び出して、この条件変数を待機しているすべてのスレッドを起動することもできます。
2 番目に、プロデューサー/コンシューマー モデルを使用して説明します
名前が示すように、このモデルを実装するには、最初に 2 つの役割 (プロデューサー、コンシューマー) が必要であることがわかります。もちろん、この 2 つの役割も必要です。重要なリソースに(一度に)双方がアクセスできるようにするには、生産者と生産者の関係(相互排他)、消費者と消費者の関係(相互排他)、生産者と消費者の関係も理解する必要があります。プロデューサー間の関係 (同期と相互排他) は、通常、1 つの場所、2 つの役割、および 3 つの関係です。コードで実装するには、プロデューサーがデータを生成し、それを消費するようにコンシューマーにシグナルを送信し、プロデューサーに生産を続行するようシグナルを送信します。
1 #include<stdio.h> 2 #include <stdlib.h> 3 #include<malloc.h> 4 #include<pthread.h> 5 #include<semaphore.h> 6 typedef int Data_type; 7 typedef int* Data_type_p; 8 static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;//初始化互斥锁 9 static pthread_cond_t needProduct=PTHREAD_COND_INITIALIZER;//初始化条件变量 10 11 12 typedef struct listnode //定义一个链表来存放数据(一个场所) 13 { 14 Data_type data; 15 struct listnode* next; 16 }list ,*listp,**listpp; 17 18 listp head=NULL; 19 20 static listp buyNode(Data_type _data) 21 { 22 listp tem=(listp)malloc(sizeof(list)); 23 if(tem) 24 { 25 tem -> data=_data; 26 tem -> next=NULL; 27 return tem; 28 } 29 return NULL; 30 } 31 void initList(listpp list) 32 { 33 *list=buyNode(0); 34 } 35 void push_list(listp list,Data_type _data) 36 { 37 listp cur=buyNode(_data); 38 listp tem=list; 39 while(tem->next) 40 { 41 tem=tem->next; 42 } 43 tem ->next=cur; 44 } 45 void deleteList(listp list) 46 { 47 if(list) 48 { 49 free(list); 50 list=NULL; 51 } 52 } 53 int pop_list(listp list,Data_type_p data) 54 { 55 if(list ->next==NULL) 56 { 57 *data =-1; 58 return -1; 59 } 60 listp tem=list->next; 61 list ->next=tem->next; 62 *data=tem->data; 63 deleteList(tem); 64 return 0; 65 } 66 void PrintList(listp list) 67 { 68 listp cur=list->next;; 69 while(cur) 70 { 71 printf("%d",cur->data); 72 fflush(stdout); 73 cur=cur->next; 74 } 75 printf("\n"); 76 } 77 void *product(void* arg)//定义生产者与生产者之间的关系(互斥) 78 { 79 int i=0; 80 while(1) 81 { 82 pthread_mutex_lock(&lock); 83 printf("product data:%d\n",i); 84 push_list(head,i++); 85 pthread_mutex_unlock(&lock); 86 printf("conduct is ok.weak up comsumer...\n"); 87 pthread_cond_signal(&needProduct);//当生产者有数据时,发送信号,唤醒消费者 88 sleep(2); 89 } 90 91 } 92 void *consumer(void* arg)//消费者与消费者之间的关系(互斥) 93 { 94 Data_type _data; 95 while(1) 96 { 97 pthread_mutex_lock(&lock); 98 while(-1==pop_list(head,&_data)) 99 { 100 pthread_cond_wait(&needProduct,&lock);//没收到生产者的消息之前就阻塞等待 101 } 102 printf("consumer data:%d\n",_data); 103 pthread_mutex_unlock(&lock); 104 sleep(1); 105 } 106 } 107 int main() 108 { 109 initList(&head); 110 pthread_t id1; 111 pthread_t id2; 112 pthread_create(&id1,NULL,product,NULL); 113 pthread_create(&id2,NULL,consumer,NULL); 114 pthread_join(id1,NULL); 115 pthread_join(id2,NULL); 116 return 0; 117 }
3. セマフォを使用してプロデューサー/コンシューマー モデルを実装します。
Mutex 変数は 0 または 1 であり、初期化されると、Mutex は 1 になり、利用可能なリソースがあることを示します。ロック時に取得 このリソースのミューテックスを 0 に減らして、利用可能なリソースがなくなったことを示します。ロックを解除するときにリソースを解放し、別の利用可能なリソースがあることを示すミューテックスを 1 に戻します。セマフォは Mutex に似ており、Mutex とは異なり、この数値は 1 より大きい場合があります。つまり、セマフォに記述されるリソースの数が 1 の場合、このときのセマフォとミューテックス ロックは同じになります。
sem_init() はセマフォを初期化します
sem_wait() P オペレーションはリソースを取得します
sem_post() V オペレーションはリソースを解放します
sem_destroy() はセマフォを破棄します
上記はリンクリストで書かれた生産者-消費者モデルです。スペースは動的に割り当てられ、プロデューサー/コンシューマー モデルは固定サイズのリング キューに基づいて書き換えられます
1 #include<stdio.h> 2 #include<pthread.h> 3 #include<semaphore.h> 4 #define PRODUCT_SIZE 20 5 #define CONSUMER_SIZE 0 6 7 sem_t produceSem; 8 sem_t consumerSem; 9 int Blank [PRODUCT_SIZE]; 10 11 void* product(void* arg) 12 { 13 int p=0; 14 while(1) 15 { 16 sem_wait(&produceSem); //申请资源。 17 int _product=rand()%100; 18 Blank[p]=_product; 19 printf("product is ok ,value is :%d\n",_product); 20 sem_post(&consumerSem);//释放资源 21 p=(p+1) % PRODUCT_SIZE; 22 sleep(rand()%3); 23 } 24 25 } 26 void* consumer(void* arg) 27 { 28 int p=0; 29 while(1) 30 { 31 sem_wait(&consumerSem);//申请资源 32 int _consumer=Blank[p]; 33 printf("consumer is ok,value is :%d\n",_consumer); 34 sem_post(&produceSem);//释放资源 35 p=(p+1)% PRODUCT_SIZE; 36 sleep(rand()%5); 37 } 38 } 39 int main() 40 { sem_init(&produceSem,0,PRODUCT_SIZE); 41 sem_init(&consumerSem,0,CONSUMER_SIZE); 42 pthread_t tid1,tid2; 43 pthread_create(&tid1,NULL,product,NULL); 44 pthread_create(&tid2,NULL,consumer,NULL); 45 pthread_join(tid1,NULL); 46 pthread_join(tid2,NULL); 47 sem_destroy(&produceSem); 48 sem_destroy(&consumerSem); 49 return 0; 50 }
4. 読み取り/書き込みロック 読み取り/書き込みロックは実際には特別なスピン ロックであり、より多くの読み取りを処理するために使用されます。この場合、共有リソースへの訪問者はリーダーとライターに分割され、リーダーは共有リソースへの読み取りアクセスのみを持ちますが、ライターは共有リソースに書き込む必要があります。この種類のロックは、スピン ロックと比較して同時実行性を向上させることができます。これは、マルチプロセッサ システムでは、複数のリーダーが同時に共有リソースにアクセスでき、リーダーの最大可能数が実際の論理 CPU 数になるためです。ライターは排他的です。読み取り/書き込みロックは、同時に 1 つのライターまたは複数のリーダーのみを持つことができます (CPU の数に関連します)。ただし、リーダーとライターの両方を同時に持つことはできません。読み取り/書き込みロックは、リーダーとライター (相互に排他的で同期)、リーダーとリーダー (関係なし)、ライターとライター (相互に排他的) 2 つのオブジェクト (リーダーとライター)、1 つの場所の 3 つの関係にも従います。
pthread_rwlock_wrlock書き込みモード、成功時に0を返し、失敗時にエラーコードを返します
pthread_rwlock_rdlock読み取りモード、成功時に0を返し、失敗時にエラーコードを返します
pthread_rwlock_init初期化
1 #include<stdio.h> 2 #include<pthread.h> 3 #define _READNUM_ 2 4 #define _WREITENUM_ 3 5 pthread_rwlock_t lock; 6 int buf=0; 7 void* read(void* reg) 8 { 9 while(1) 10 { 11 if(pthread_rwlock_tryrdlock(&lock) != 0)//读方式 12 { 13 printf("writer is write! reader wait...\n"); 14 } 15 else 16 { 17 printf("reader is reading,val is %d\n",buf); 18 pthread_rwlock_unlock(&lock); 19 } 20 sleep(2); 21 } 22 } 23 void* write(void* reg) 24 { 25 while(1) 26 { 27 if(pthread_rwlock_trywrlock(&lock) != 0)//写方式 28 { 29 printf("reader is reading ! writer wait...\n"); 30 sleep(1); 31 } 32 else 33 { 34 buf++; 35 printf("writer is writing,val is %d\n",buf); 36 pthread_rwlock_unlock(&lock); 37 38 } 39 sleep(1); 40 } 41 } 42 int main() 43 { 44 pthread_rwlock_init(&lock,NULL); 45 pthread_t tid; 46 int i=0; 47 for(i;i< _WREITENUM_;i++) 48 { 49 pthread_create(&tid,NULL,write,NULL); 50 } 51 52 for(i; i< _READNUM_;i++) 53 { 54 pthread_create(&tid,NULL,read,NULL); 55 } 56 pthread_join(tid,NULL); 57 sleep(100); 58 return 0; 59 }
上記はLinux--Condition Variable(条件変数)を使用するものです。プロデューサーとコンシューマーの実装 リーダー モデルと読み取り/書き込みロックの内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Centosとubuntuの重要な違いは次のとおりです。起源(CentosはRed Hat、for Enterprises、UbuntuはDebianに由来します。個人用のDebianに由来します)、パッケージ管理(CentosはYumを使用し、安定性に焦点を当てます。チュートリアルとドキュメント)、使用(Centosはサーバーに偏っています。Ubuntuはサーバーやデスクトップに適しています)、その他の違いにはインストールのシンプルさが含まれます(Centos is Thin)

Dockerデスクトップの使用方法は? Dockerデスクトップは、ローカルマシンでDockerコンテナを実行するためのツールです。使用する手順には次のものがあります。1。Dockerデスクトップをインストールします。 2。Dockerデスクトップを開始します。 3。Docker Imageを作成します(DockerFileを使用); 4. Docker画像をビルド(Docker Buildを使用); 5。Dockerコンテナを実行します(Docker Runを使用)。

Centosのインストール手順:ISO画像をダウンロードし、起動可能なメディアを燃やします。起動してインストールソースを選択します。言語とキーボードのレイアウトを選択します。ネットワークを構成します。ハードディスクをパーティション化します。システムクロックを設定します。ルートユーザーを作成します。ソフトウェアパッケージを選択します。インストールを開始します。インストールが完了した後、ハードディスクから再起動して起動します。

Centosは廃止されました、代替品には次のものが含まれます。1。RockyLinux(最高の互換性)。 2。アルマリン(Centosと互換性); 3。Ubuntuサーバー(設定が必要); 4。RedHat Enterprise Linux(コマーシャルバージョン、有料ライセンス); 5。OracleLinux(CentosとRhelと互換性があります)。移行する場合、考慮事項は次のとおりです。互換性、可用性、サポート、コスト、およびコミュニティサポート。

Dockerプロセス表示方法:1。DockerCLIコマンド:Docker PS; 2。SystemDCLIコマンド:SystemCTL Status Docker; 3。CLIコマンドを作成するDocker:Docker-Compose PS。 4。プロセスエクスプローラー(Windows); 5。 /procディレクトリ(Linux)。

DockerはLinuxカーネル機能を使用して、効率的で孤立したアプリケーションランニング環境を提供します。その作業原則は次のとおりです。1。ミラーは、アプリケーションを実行するために必要なすべてを含む読み取り専用テンプレートとして使用されます。 2。ユニオンファイルシステム(UnionFS)は、違いを保存するだけで、スペースを節約し、高速化する複数のファイルシステムをスタックします。 3.デーモンはミラーとコンテナを管理し、クライアントはそれらをインタラクションに使用します。 4。名前空間とcgroupsは、コンテナの分離とリソースの制限を実装します。 5.複数のネットワークモードは、コンテナの相互接続をサポートします。これらのコア概念を理解することによってのみ、Dockerをよりよく利用できます。

障害のあるDocker画像ビルドのトラブルシューティング手順:DockerFileの構文と依存関係バージョンを確認します。ビルドコンテキストに必要なソースコードと依存関係が含まれているかどうかを確認します。エラーの詳細については、ビルドログを表示します。 -targetオプションを使用して、階層フェーズを構築して障害点を識別します。 Dockerエンジンの最新バージョンを使用してください。 -t [image-name]:デバッグモードで画像を作成して、問題をデバッグします。ディスクスペースを確認し、十分であることを確認してください。 Selinuxを無効にして、ビルドプロセスへの干渉を防ぎます。コミュニティプラットフォームに助けを求め、DockerFilesを提供し、より具体的な提案のためにログの説明を作成します。

VSコードシステムの要件:オペレーティングシステム:オペレーティングシステム:Windows 10以降、MACOS 10.12以上、Linux Distributionプロセッサ:最小1.6 GHz、推奨2.0 GHz以上のメモリ:最小512 MB、推奨4 GB以上のストレージスペース:最低250 MB以上:その他の要件を推奨:安定ネットワーク接続、XORG/WAYLAND(Linux)
