logo

C でのマルチスレッド

導入:

C では、用語は 「マルチスレッド」 多数の使用法を説明します スレッド 同時に。各スレッドは次のことを行います 別のタスク 。マルチスレッドの同時実行の性質により、多くのタスクが一度に実行される可能性があります。さらに、 マルチスレッド を減らす CPUのリソース使用量 。マルチタスクには 2 つのカテゴリがあります。 プロセスベースの そして スレッドベースの 。マルチスレッドとして説明されている場合は、少なくとも 2 つ以上のスレッドが同じプロセスで同時に実行されていることを意味します。 C のマルチスレッドを理解するには、まずスレッドとプロセスが何であるかを理解する必要があります。より理解を深めるために、これらの主題を見てみましょう。

JavaScript サンプルコードの例

プロセスとスレッドとは何ですか?

それは 基本的な建物 ブロック あらゆるプロセスの実行。プログラムは複数のプロセスで構成され、各プロセスはより基本的な単位であるスレッドで構成されます。したがって、スレッドはプロセスの基本的な構成要素、または CPU 使用率を共同で決定するより単純な単位と考えることができます。

スレッドには次の項目が含まれます。

スレッドID:

特別です スレッドID これはスレッドの形成時に生成され、その特定のスレッドの存続期間中保持されます。

プログラムカウンター:

という値です。 ハードウェアの負荷

登録されたセット:

のコレクションです 共通レジスタ

スタック:

その名残です 特定のスレッド

さらに、2 つのスレッドが同じプロセスで同時に動作する場合、それらは共有します。 コード データセクション 、ファイルなどのその他のオペレーティング システム リソース 開く そして 信号 。従来のプロセスの一種である重量プロセスは、1 つのスレッドを制御できます。ただし、マルチスレッド制御には、複数のタスクを開いて同時に実行する機能があります。スレッドを使用するとシステムの効率が大幅に向上するため、スレッドが役立ちます。

間の区別 シングル そして マルチスレッド Cで説明します。まず第一に、それは シングルスレッドプロセス 。その結果、ブロック全体 ( コード、データ、 など - は 1 つのプロセスとみなされ、そのプロセスには 1 つのスレッドしかありません。これは、このテクニックが一度に 1 つのタスクだけを完了できることを意味します。しかし、 マルチスレッドプロセス それはこれに対抗するものです。といった活動があります コード、スタック、データ 、 そして ファイル 同様に、それらは複数のスレッドによって実行され、それぞれが独自のスタックとレジスタを持っています。この状況では多数のタスクを一度に完了できるため、このプロセスは「 マルチスレッドプロセス

糸には 2 つの種類があります。

ユーザーレベルのスレッド:

名前が示すとおり、これはユーザー レベルです。カーネルにはそのデータへのアクセスが与えられません。

カーネルレベルのスレッド

スレッドの種類は、システムのカーネルお​​よびオペレーティング システムとスレッドの関係を指します。

プロセス- プログラムを実行するために必要な一連のステップを「 プロセス 。プログラムは実行してもすぐには実行されません。これは、組織的な方法で順番に実行されるいくつかの基本的なステップに分割され、最終的にプロセスの実行につながります。

より小さなステップに分割されたプロセスは、 'クローンまたは子プロセス', 元のプロセスは と呼ばれますが、 「親」プロセス 。メモリ内では、各プロセスは他のプロセスと共有されない一定量のスペースを使用します。

プロシージャは実行前にいくつかの段階を経ます。

Java 8の機能

新しい-

この状況では、新しいプロセスは 生成された

準備ができて-

プロセスが準備され、プロセッサが割り当てられるのを待っているとき、プロセスはこの状態になります。

ランニング-

プロセスがアクティブなとき、それが状態になります。

待っている-

プロセスがこの状態にあるとき、何かが 待っている 発生する。

終了しました-

手続き中の様子です。

なぜ C はマルチスレッドなのでしょうか?

マルチスレッド化 C のアイデアを並列処理を通じて活用して、 アプリケーションの機能 。ブラウザ ウィンドウで複数のタブを開いている場合を考えてみましょう。次に、各タブは同時に動作し、タブと呼ばれる場合があります。 。使用すると仮定すると マイクロソフトエクセル 、1つのスレッドが管理します テキストの書式設定 、そして 1 つのスレッドは ハンドル入力 。したがって、C のマルチスレッド機能を使用すると、複数のタスクを一度に簡単に実行できます。スレッドの作成が大幅に高速化されます。スレッド間のコンテキスト転送はより迅速に行われます。さらに、スレッド間の通信がより高速になり、スレッドの終了も簡単になります。

マルチスレッド用の C プログラムを作成するには?

マルチスレッド アプリケーションは C 言語には組み込まれていませんが、オペレーティング システムによっては可能です。の thread.h 標準ライブラリ マルチスレッドのアイデアを実装するために使用されます C 。ただし、現時点ではこれを実行できるコンパイラはありません。次のようなプラットフォーム固有の実装を採用する必要があります。 「ポシックス」 ヘッダー ファイルを使用したスレッド ライブラリ pthread.h , C でマルチスレッドを使用したい場合。 「Pスレッド」 はこれの別名です。あ POSIX スレッドは次の方法で作成できます。

 #include pthread_create (thread, attr, start_routine, arg) 

この場合、 Pthread_create スレッドを実行可能にするために新しいスレッドを作成します。コード内で何度でも C でマルチスレッドを実装できます。前述のパラメータとその説明がここにリストされます。

糸:

それは 特異な識別 それは サブプロセスが返す

属性:

スレッドの属性を設定したい場合はこれを使用します 不透明属性

開始ルーチン:

いつ 開始ルーチン が生成されると、スレッドはルーチンを実行します。

引数:

パラメータ 開始ルーチン 受け取ります。 ヌル 引数が指定されていない場合に使用されます。

Java例外処理

特定の C マルチスレッドの例

C におけるマルチスレッドの問題の例をいくつか示します。

1. リーダーライターの問題

プロセス同期に関するオペレーティング システムの一般的な問題は次のとおりです。 リーダー/ライターの問題 。次のようなデータベースがあると仮定します。 読者 そして 作家 、2 つの異なるユーザー カテゴリにアクセスできます。 読者 できるのは彼らだけです 読む データベース、一方 作家 データベースを読み取り、更新できるのは彼らだけです。使ってみましょう IRCTC 簡単な例として。特定のステータスを確認したい場合 列車番号 、システムに列車番号を入力するだけで、関連する列車情報が表示されます。ここにはウェブサイト上に存在する情報のみが表示されます。読み取り演算子はこれです。ただし、チケットを予約したい場合は、チケット予約フォームに名前、年齢などの詳細を記入する必要があります。したがって、ここで書き込み操作を実行します。いくつかの調整が行われる予定です IRCTC データベース

問題は、複数の人が同時にアクセスしようとしているということです。 IRCTC データベース 。彼らはもしかしたら ライター または 読者 。この問題は、リーダーがすでにデータベースを利用しており、ライターが同じデータを操作するために同時にデータベースにアクセスする場合に発生します。ライターがデータベースを使用し、リーダーがデータベースと同じ情報にアクセスする場合、別の問題が発生します。第三に、あるライターがデータベースを更新している間に別のライターが同じデータベース上のデータを更新しようとすると、問題が発生します。 4 番目のシナリオは、2 人のリーダーが同じ資料を取得しようとしたときに発生します。これらの問題はすべて、リーダーとライターが同じデータベース データを使用する場合に発生します。

セマフォはこの問題を解決するために採用される方法です。この問題の使用方法を図で見てみましょう。

リーダーのプロセス:

 #include #include #include int rc = 0; // Reader count int data = 0; // Shared data pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_twrt = PTHREAD_COND_INITIALIZER; void* reader(void* arg) { int reader_id = *(int*)arg; pthread_mutex_lock(&mutex); rc++; if (rc == 1) pthread_cond_wait(&wrt, &mutex); pthread_mutex_unlock(&mutex); // Reading the shared data printf('Reader %d reads data: %d
&apos;, reader_id, data); pthread_mutex_lock(&amp;mutex); rc--; if (rc == 0) pthread_cond_signal(&amp;wrt); pthread_mutex_unlock(&amp;mutex); return NULL; } int main() { pthread_treaders[5]; // Assuming 5 reader threads int reader_ids[5]; for (int i = 0; i<5; i++) { reader_ids[i]="i" + 1; pthread_create(&readers[i], null, reader, &reader_ids[i]); } joining reader threads for (int i="0;" i< 5; pthread_join(readers[i], null); return 0; < pre> <p> <strong>Output:</strong> </p> <pre> Reader 1 reads data: 0 Reader 2 reads data: 0 Reader 3 reads data: 0 Reader 4 reads data: 0 Reader 5 reads data: 0 </pre> <p> <strong>Explanation:</strong> </p> <p>In this code, we have the shared variable data and the <strong> <em>reader count rc</em> </strong> . The <strong> <em>wrt condition</em> </strong> variable is used to limit access for the <strong> <em>writer process</em> </strong> , and the <strong> <em>mutex</em> </strong> is used to guarantee mutual exclusion for accessing the shared data.</p> <p>The reader process is represented by the <strong> <em>reader() function</em> </strong> . The <strong> <em>reader count (rc)</em> </strong> is increased before attaining the <strong> <em>mutex lock</em> </strong> . It uses <strong> <em>pthread_cond_wait()</em> </strong> to wait on the <strong> <em>wrt condition</em> </strong> variable if it is the <strong> <em>first reader (rc == 1)</em> </strong> . As a result, writers will be prevented from writing until all readers have completed.</p> <p>The reader process checks if it was the <strong> <em>last reader (rc == 0)</em> </strong> and lowers the reader <strong> <em>count (rc--)</em> </strong> after reading the shared data. If it was, <strong> <em>pthread_cond_signal()</em> </strong> signals the <strong> <em>wrt condition</em> </strong> variable to let waiting writer processes continue.</p> <p>Using the <strong> <em>pthread_create()</em> </strong> and <strong> <em>pthread_join() functions</em> </strong> , we <strong> <em>new</em> </strong> and <strong> <em>join</em> </strong> multiple reader threads in the <strong> <em>main() function</em> </strong> . An individual ID is assigned to each reader thread for identifying purposes.</p> <h3>Writer process:</h3> <pre> wait(wrt); . . WRITE INTO THE OBJECT . signal(wrt); </pre> <p>In the above example, same as the <strong> <em>reader process</em> </strong> , an operation known as the wait operation is carried out on <strong> <em>&apos;wrt&apos;</em> </strong> when a user wishes to access the data or object. After that, the new user won&apos;t be able to access the object. And once the user has finished writing, another signal operation is performed on <strong> <em>wrt</em> </strong> .</p> <h3>2. lock and unlock problem:</h3> <p>The idea of a <strong> <em>mutex</em> </strong> is utilized in multithreading in C to guarantee that there won&apos;t be a <strong> <em>race condition</em> </strong> between the <strong> <em>threads</em> </strong> . When multiple threads begin processing the same data at once, this circumstance is known as <strong> <em>racing</em> </strong> . However, if these circumstances exist, we must. We use the <strong> <em>mutex&apos;s lock()</em> </strong> and <strong> <em>unlock() functions</em> </strong> to secure a particular section of code for a specific thread. Such that, another thread cannot begin performing the same operation. The <strong> <em>&apos;critical section/region&apos;</em> </strong> is the name given to this protected code area. Before using the shared resources, we set up a lot in a certain area, and once we&apos;ve finished using them, we unlock them once more.</p> <p>Let&apos;s examine the operation of the mutex for locking and unlocking in multithreading in C:</p> <p> <strong>Example:</strong> </p> <pre> #include #include #include pthread_mutex_tmy_mutex = PTHREAD_MUTEX_INITIALIZER; int shared_data = 0; void *thread_function(void *arg) { pthread_mutex_lock(&amp;my_mutex); shared_data++; // Modify the shared data printf(&apos;Thread %ld: Shared data modified. New value: %d
&apos;, (long)arg, shared_data); pthread_mutex_unlock(&amp;my_mutex); return NULL; } int main() { pthread_tthreads[5]; // Assuming 5 threads for (int i = 0; i<5; i++) { if (pthread_create(&threads[i], null, thread_function, (void *)(long)(i + 1)) !="0)" fprintf(stderr, 'error creating thread %d
', i 1); return 1; } for (int i< 5; (pthread_join(threads[i], null) joining 0; < pre> <p> <strong>Output:</strong> </p> <pre> Thread 1: Shared data modified. New value: 1 Thread 2: Shared data modified. New value: 2 Thread 3: Shared data modified. New value: 3 Thread 4: Shared data modified. New value: 4 Thread 5: Shared data modified. New value: 5 </pre> <p> <strong>Explanation:</strong> </p> <p>In this above example, we explain how we <strong> <em>lock</em> </strong> and <strong> <em>unlock</em> </strong> a certain region of code that shields us from the racing situation. <strong> <em>&apos;pthread_mutex_t&apos;</em> </strong> is used as an <strong> <em>initializer</em> </strong> in the example above. <strong> <em>&apos;pthread_mutex_lock&apos;</em> </strong> is then <strong> <em>written</em> </strong> before the beginning of the code that we want to lock. The coding that we wish to lock is finished after that. After that, the locking of the code is terminated using <strong> <em>&apos;pthread_mutex_unlock&apos;</em> </strong> ; going forward, no code will be in lock mode.</p> <h2>The Dining Philosopher Problem:</h2> <p>One of the classic issues with synchronization is the <strong> <em>dining philosopher issue</em> </strong> . Simple resource allocation for several processes is required but shouldn&apos;t result in a <strong> <em>stalemate</em> </strong> or <strong> <em>hunger</em> </strong> . The <strong> <em>dining philosopher problem</em> </strong> can be viewed as a straightforward representation of a number of processes, each of which is demanding resources. Since each of these processes requires a resource allocation, it is necessary to distribute those resources across all of the processes so that no one process ever gets stuck or stops working.</p> <p>Assume there are five philosophers seated at a <strong> <em>circle-shaped table</em> </strong> . They eat at one point and ponder about something at another. Around the round table, the philosophers are evenly spaced out on the chairs. Additionally, there is a bowl of rice and five chopsticks for each philosopher in the middle of the table. When the philosopher feels she cannot interact with her colleagues who are seated nearby.</p> <p>A philosopher occasionally takes up two chopsticks when she becomes hungry. She chooses two chopsticks from her neighbors-one on her <strong> <em>left</em> </strong> and one on her <strong> <em>right</em> </strong> -that are within easy reach. But the philosopher should never pick up more than one chopstick at once. She will obviously be unable to pick up the chopstick that the neighbor is using.</p> <p> <strong>Example:</strong> </p> <p>Let&apos;s use an example to demonstrate how this is implemented in C.</p> <pre> #include #include #include #include #include pthread_tphilosopher[5]; pthread_mutex_tchopstick[5]; void *func(void *arg) { int n = *(int *)arg; printf(&apos;
Philosopher %d is thinking.&apos;, n); pthread_mutex_lock(&amp;chopstick[n]); pthread_mutex_lock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d is eating.&apos;, n); sleep(3); pthread_mutex_unlock(&amp;chopstick[n]); pthread_mutex_unlock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d Finished eating &apos;, n); return NULL; } int main() { int i, k; void *message; for (i = 0; i<5; i++) { k="pthread_mutex_init(&amp;chopstick[i]," null); if (k !="0)" printf('failed to initialize the mutex
'); exit(1); } for (i="0;" i< 5; null, func, (void *)&i); printf('error in thread creation.
'); &message); join thread.
'); printf('mutex destroyed.
'); return 0; < pre> <p> <strong>Output:</strong> </p> <pre> Philosopher 0 is thinking. Philosopher 1 is thinking. Philosopher 2 is thinking. Philosopher 3 is thinking. Philosopher 4 is thinking. Philosopher 0 is eating. Philosopher 1 is eating. Philosopher 2 is eating. Philosopher 3 is eating. Philosopher 4 is eating. Philosopher 0 Finished eating Philosopher 1 Finished eating Philosopher 2 Finished eating Philosopher 3 Finished eating Philosopher 4 Finished eating </pre> <p> <strong>Explanation:</strong> </p> <p> <strong> <em>Chopsticks</em> </strong> can be represented by a semaphore. Since there are <strong> <em>chopsticks</em> </strong> on the table and no philosopher has chosen one, all of the chopsticks&apos; components are first initialized to <strong> <em>1</em> </strong> . Now that <strong> <em>chopstick[i]</em> </strong> has been chosen as the first <strong> <em>chopstick. chopstick[i]</em> </strong> and <strong> <em>chopstick[(i+1)%5]</em> </strong> are subject to the first wait operation. These <strong> <em>chopsticks&apos; wait operation</em> </strong> indicates that the philosopher has picked them up. The eating process begins once the philosopher selects his <strong> <em>chopstick</em> </strong> . The signal operation is now carried out on the <strong> <em>chopsticks [i]</em> </strong> and <strong> <em>[(i+1)%5]</em> </strong> once the philosopher has finished eating. The philosopher then turns back to sleep.</p> <p>To determine whether the <strong> <em>subthread</em> </strong> has joined the main thread or not, we used the <strong> <em>pthread_join function</em> </strong> . Similarly, we have checked whether the <strong> <em>mutex</em> </strong> lock has been initialized using the <strong> <em>pthread_mutex_init</em> </strong> method.</p> <p>To initialize and verify whether the new thread was created or not, we utilized the <strong> <em>pthread_create function</em> </strong> . Similar to this, we destroyed the <strong> <em>mutex lock</em> </strong> using the <strong> <em>pthread_mutex_destroy</em> </strong> function.</p> <h2>The Producer-Consumer Problem:</h2> <p>A common issue with multithreading process synchronization is the <strong> <em>producer-consumer problem</em> </strong> . Two processes are present in it: the first is the <strong> <em>producer&apos;s process</em> </strong> , and the second is the <strong> <em>consumer&apos;s process</em> </strong> . Furthermore, it is assumed that both operations are occurring concurrently in parallel. Additionally, they are a cooperative process, which implies that they are sharing something with one another. It is important that when the buffer is <strong> <em>full</em> </strong> , the producer cannot add data. When the buffer is empty, the consumer cannot extract data from the buffer because the common buffer size between the producer and the consumer is <strong> <em>fixed</em> </strong> . The issue is stated in this way. Hence, to implement the Producer-Consumer problem and solve it, we shall employ the idea of parallel programming.</p> <p> <strong>Example:</strong> </p> <pre> #include #include int mutex = 1, full = 0, empty = 3, x = 0; int main() { int n; void producer(); void consumer(); int wait(int); int signal(int); printf(&apos;
1.producer
2.consumer
3.for exit&apos;); while (1) { printf(&apos;
 Please enter your choice:&apos;); scanf(&apos;%d&apos;, &amp;n); switch (n) { case 1: if ((mutex == 1) &amp;&amp; (empty != 0)) producer(); else printf(&apos;Oops!! the buffer is full!!&apos;); break; case 2: if ((mutex == 1) &amp;&amp; (full != 0)) consumer(); else printf(&apos;Oops!! the buffer is empty!!&apos;); break; case 3: exit(0); break; } } return 0; } int wait(int s) { return (--s); } int signal(int s) { return (++s); } void producer() { mutex = wait(mutex); full = signal(full); empty = wait(empty); x++; printf(&apos;
Item produced by the Producer %d&apos;, x); mutex = signal(mutex); } void consumer() { mutex = wait(mutex); full = wait(full); empty = signal(empty); printf(&apos;
Item consumed by the Consumer %d&apos;, x); x--; mutex = signal(mutex); } </pre> <p> <strong>Output:</strong> </p> <pre> 1. producer 2. consumer 3. for exit Please enter your choice: </pre> <p> <strong>Explanation:</strong> </p> <p>We perform two tasks. The functions <strong> <em>consumer()</em> </strong> and <strong> <em>producer()</em> </strong> indicate the status and operation of the <strong> <em>consumer</em> </strong> and <strong> <em>producer</em> </strong> . The <strong> <em>producer() method</em> </strong> will create the <strong> <em>mutex lock</em> </strong> and determine whether the buffer is <strong> <em>full</em> </strong> when it is called. When the buffer is full, nothing will be produced. If not, it will <strong> <em>create</em> </strong> , and then, after the <strong> <em>production</em> </strong> , it will put itself to sleep to unlock the <strong> <em>mutex lock</em> </strong> . Like the <strong> <em>producer</em> </strong> , the consumer first creates the <strong> <em>mutex lock</em> </strong> , checks the <strong> <em>buffer</em> </strong> , consumes the <strong> <em>product</em> </strong> , and then releases the lock before going back to sleep.</p> <p>A <strong> <em>counter (x)</em> </strong> will be used during manufacturing and will keep growing until the manufacturer produces the item. However, the consumer will make fewer of the same manufactured <strong> <em>item (x)</em> </strong> .</p> <h2>Conclusion:</h2> <p>The idea of using <strong> <em>two</em> </strong> or <strong> <em>more threads</em> </strong> to execute a program is known as <strong> <em>multithreading</em> </strong> in the C programming language. <strong> <em>Multithreading</em> </strong> allows for the simultaneous execution of several tasks. The simplest executable component of a program is a <strong> <em>thread</em> </strong> . The process is the idea that a task can be completed by breaking it up into several smaller <strong> <em>sub-processes</em> </strong> .</p> <p>The header file <strong> <em>pthread.h</em> </strong> is required in order to implement multithreading in C since it cannot be done directly.</p> <hr></5;></pre></5;></pre></5;>

説明:

このコードには、シェア変数データと リーダー数 rc 。の 最悪の状態 変数は、へのアクセスを制限するために使用されます。 ライタープロセス 、 そしてその ミューテックス 共有データにアクセスする際の相互排他を保証するために使用されます。

リーダーのプロセスは次のように表されます。 リーダー()関数 。の リーダー数 (rc) に達する前に増加します ミューテックスロック 。それは使用しています pthread_cond_wait() を待つ 最悪の状態 変数の場合、 最初のリーダー (rc == 1) 。その結果、ライターはすべてのリーダーが完了するまで書き込みできなくなります。

リーダープロセスは、それが 最後のリーダー (rc == 0) そしてリーダーを下げます カウント (rc--) 共有データを読み取った後。もしそうなら、 pthread_cond_signal() 信号を送ります 最悪の状態 変数を使用して、待機中のライタープロセスを続行できるようにします。

を使用して、 pthread_create() そして pthread_join() 関数 、 私たちは 新しい そして 参加する の複数のリーダー スレッド メイン機能 。各リーダースレッドには、識別のために個別の ID が割り当てられます。

ライタープロセス:

 wait(wrt); . . WRITE INTO THE OBJECT . signal(wrt); 

上の例では、 リーダープロセス 、待機操作として知られる操作が実行されます。 'に関して' ユーザーがデータまたはオブジェクトにアクセスしたいとき。その後、新しいユーザーはオブジェクトにアクセスできなくなります。ユーザーが書き込みを終了すると、別のシグナル操作が実行されます。 に関して

2.ロックとロック解除の問題:

というアイデア ミューテックス C のマルチスレッドで利用され、 競合状態 間に スレッド 。複数のスレッドが同時に同じデータの処理を開始する場合、この状況は次のように呼ばれます。 レーシング 。ただし、このような状況が存在する場合は、そうしなければなりません。私たちが使用するのは、 ミューテックスのlock() そして ロック解除()関数 特定のスレッドのコードの特定のセクションを保護します。そのため、別のスレッドは同じ操作の実行を開始できません。の 「重要セクション/領域」 は、この保護されたコード領域に付けられた名前です。共有リソースを使用する前に、特定のエリアにたくさん設置し、使用し終わったら、もう一度ロックを解除します。

C でのマルチスレッドでのロックとロック解除のためのミューテックスの動作を調べてみましょう。

例:

 #include #include #include pthread_mutex_tmy_mutex = PTHREAD_MUTEX_INITIALIZER; int shared_data = 0; void *thread_function(void *arg) { pthread_mutex_lock(&amp;my_mutex); shared_data++; // Modify the shared data printf(&apos;Thread %ld: Shared data modified. New value: %d
&apos;, (long)arg, shared_data); pthread_mutex_unlock(&amp;my_mutex); return NULL; } int main() { pthread_tthreads[5]; // Assuming 5 threads for (int i = 0; i<5; i++) { if (pthread_create(&threads[i], null, thread_function, (void *)(long)(i + 1)) !="0)" fprintf(stderr, \'error creating thread %d
\', i 1); return 1; } for (int i< 5; (pthread_join(threads[i], null) joining 0; < pre> <p> <strong>Output:</strong> </p> <pre> Thread 1: Shared data modified. New value: 1 Thread 2: Shared data modified. New value: 2 Thread 3: Shared data modified. New value: 3 Thread 4: Shared data modified. New value: 4 Thread 5: Shared data modified. New value: 5 </pre> <p> <strong>Explanation:</strong> </p> <p>In this above example, we explain how we <strong> <em>lock</em> </strong> and <strong> <em>unlock</em> </strong> a certain region of code that shields us from the racing situation. <strong> <em>&apos;pthread_mutex_t&apos;</em> </strong> is used as an <strong> <em>initializer</em> </strong> in the example above. <strong> <em>&apos;pthread_mutex_lock&apos;</em> </strong> is then <strong> <em>written</em> </strong> before the beginning of the code that we want to lock. The coding that we wish to lock is finished after that. After that, the locking of the code is terminated using <strong> <em>&apos;pthread_mutex_unlock&apos;</em> </strong> ; going forward, no code will be in lock mode.</p> <h2>The Dining Philosopher Problem:</h2> <p>One of the classic issues with synchronization is the <strong> <em>dining philosopher issue</em> </strong> . Simple resource allocation for several processes is required but shouldn&apos;t result in a <strong> <em>stalemate</em> </strong> or <strong> <em>hunger</em> </strong> . The <strong> <em>dining philosopher problem</em> </strong> can be viewed as a straightforward representation of a number of processes, each of which is demanding resources. Since each of these processes requires a resource allocation, it is necessary to distribute those resources across all of the processes so that no one process ever gets stuck or stops working.</p> <p>Assume there are five philosophers seated at a <strong> <em>circle-shaped table</em> </strong> . They eat at one point and ponder about something at another. Around the round table, the philosophers are evenly spaced out on the chairs. Additionally, there is a bowl of rice and five chopsticks for each philosopher in the middle of the table. When the philosopher feels she cannot interact with her colleagues who are seated nearby.</p> <p>A philosopher occasionally takes up two chopsticks when she becomes hungry. She chooses two chopsticks from her neighbors-one on her <strong> <em>left</em> </strong> and one on her <strong> <em>right</em> </strong> -that are within easy reach. But the philosopher should never pick up more than one chopstick at once. She will obviously be unable to pick up the chopstick that the neighbor is using.</p> <p> <strong>Example:</strong> </p> <p>Let&apos;s use an example to demonstrate how this is implemented in C.</p> <pre> #include #include #include #include #include pthread_tphilosopher[5]; pthread_mutex_tchopstick[5]; void *func(void *arg) { int n = *(int *)arg; printf(&apos;
Philosopher %d is thinking.&apos;, n); pthread_mutex_lock(&amp;chopstick[n]); pthread_mutex_lock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d is eating.&apos;, n); sleep(3); pthread_mutex_unlock(&amp;chopstick[n]); pthread_mutex_unlock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d Finished eating &apos;, n); return NULL; } int main() { int i, k; void *message; for (i = 0; i<5; i++) { k="pthread_mutex_init(&amp;chopstick[i]," null); if (k !="0)" printf(\'failed to initialize the mutex
\'); exit(1); } for (i="0;" i< 5; null, func, (void *)&i); printf(\'error in thread creation.
\'); &message); join thread.
\'); printf(\'mutex destroyed.
\'); return 0; < pre> <p> <strong>Output:</strong> </p> <pre> Philosopher 0 is thinking. Philosopher 1 is thinking. Philosopher 2 is thinking. Philosopher 3 is thinking. Philosopher 4 is thinking. Philosopher 0 is eating. Philosopher 1 is eating. Philosopher 2 is eating. Philosopher 3 is eating. Philosopher 4 is eating. Philosopher 0 Finished eating Philosopher 1 Finished eating Philosopher 2 Finished eating Philosopher 3 Finished eating Philosopher 4 Finished eating </pre> <p> <strong>Explanation:</strong> </p> <p> <strong> <em>Chopsticks</em> </strong> can be represented by a semaphore. Since there are <strong> <em>chopsticks</em> </strong> on the table and no philosopher has chosen one, all of the chopsticks&apos; components are first initialized to <strong> <em>1</em> </strong> . Now that <strong> <em>chopstick[i]</em> </strong> has been chosen as the first <strong> <em>chopstick. chopstick[i]</em> </strong> and <strong> <em>chopstick[(i+1)%5]</em> </strong> are subject to the first wait operation. These <strong> <em>chopsticks&apos; wait operation</em> </strong> indicates that the philosopher has picked them up. The eating process begins once the philosopher selects his <strong> <em>chopstick</em> </strong> . The signal operation is now carried out on the <strong> <em>chopsticks [i]</em> </strong> and <strong> <em>[(i+1)%5]</em> </strong> once the philosopher has finished eating. The philosopher then turns back to sleep.</p> <p>To determine whether the <strong> <em>subthread</em> </strong> has joined the main thread or not, we used the <strong> <em>pthread_join function</em> </strong> . Similarly, we have checked whether the <strong> <em>mutex</em> </strong> lock has been initialized using the <strong> <em>pthread_mutex_init</em> </strong> method.</p> <p>To initialize and verify whether the new thread was created or not, we utilized the <strong> <em>pthread_create function</em> </strong> . Similar to this, we destroyed the <strong> <em>mutex lock</em> </strong> using the <strong> <em>pthread_mutex_destroy</em> </strong> function.</p> <h2>The Producer-Consumer Problem:</h2> <p>A common issue with multithreading process synchronization is the <strong> <em>producer-consumer problem</em> </strong> . Two processes are present in it: the first is the <strong> <em>producer&apos;s process</em> </strong> , and the second is the <strong> <em>consumer&apos;s process</em> </strong> . Furthermore, it is assumed that both operations are occurring concurrently in parallel. Additionally, they are a cooperative process, which implies that they are sharing something with one another. It is important that when the buffer is <strong> <em>full</em> </strong> , the producer cannot add data. When the buffer is empty, the consumer cannot extract data from the buffer because the common buffer size between the producer and the consumer is <strong> <em>fixed</em> </strong> . The issue is stated in this way. Hence, to implement the Producer-Consumer problem and solve it, we shall employ the idea of parallel programming.</p> <p> <strong>Example:</strong> </p> <pre> #include #include int mutex = 1, full = 0, empty = 3, x = 0; int main() { int n; void producer(); void consumer(); int wait(int); int signal(int); printf(&apos;
1.producer
2.consumer
3.for exit&apos;); while (1) { printf(&apos;
 Please enter your choice:&apos;); scanf(&apos;%d&apos;, &amp;n); switch (n) { case 1: if ((mutex == 1) &amp;&amp; (empty != 0)) producer(); else printf(&apos;Oops!! the buffer is full!!&apos;); break; case 2: if ((mutex == 1) &amp;&amp; (full != 0)) consumer(); else printf(&apos;Oops!! the buffer is empty!!&apos;); break; case 3: exit(0); break; } } return 0; } int wait(int s) { return (--s); } int signal(int s) { return (++s); } void producer() { mutex = wait(mutex); full = signal(full); empty = wait(empty); x++; printf(&apos;
Item produced by the Producer %d&apos;, x); mutex = signal(mutex); } void consumer() { mutex = wait(mutex); full = wait(full); empty = signal(empty); printf(&apos;
Item consumed by the Consumer %d&apos;, x); x--; mutex = signal(mutex); } </pre> <p> <strong>Output:</strong> </p> <pre> 1. producer 2. consumer 3. for exit Please enter your choice: </pre> <p> <strong>Explanation:</strong> </p> <p>We perform two tasks. The functions <strong> <em>consumer()</em> </strong> and <strong> <em>producer()</em> </strong> indicate the status and operation of the <strong> <em>consumer</em> </strong> and <strong> <em>producer</em> </strong> . The <strong> <em>producer() method</em> </strong> will create the <strong> <em>mutex lock</em> </strong> and determine whether the buffer is <strong> <em>full</em> </strong> when it is called. When the buffer is full, nothing will be produced. If not, it will <strong> <em>create</em> </strong> , and then, after the <strong> <em>production</em> </strong> , it will put itself to sleep to unlock the <strong> <em>mutex lock</em> </strong> . Like the <strong> <em>producer</em> </strong> , the consumer first creates the <strong> <em>mutex lock</em> </strong> , checks the <strong> <em>buffer</em> </strong> , consumes the <strong> <em>product</em> </strong> , and then releases the lock before going back to sleep.</p> <p>A <strong> <em>counter (x)</em> </strong> will be used during manufacturing and will keep growing until the manufacturer produces the item. However, the consumer will make fewer of the same manufactured <strong> <em>item (x)</em> </strong> .</p> <h2>Conclusion:</h2> <p>The idea of using <strong> <em>two</em> </strong> or <strong> <em>more threads</em> </strong> to execute a program is known as <strong> <em>multithreading</em> </strong> in the C programming language. <strong> <em>Multithreading</em> </strong> allows for the simultaneous execution of several tasks. The simplest executable component of a program is a <strong> <em>thread</em> </strong> . The process is the idea that a task can be completed by breaking it up into several smaller <strong> <em>sub-processes</em> </strong> .</p> <p>The header file <strong> <em>pthread.h</em> </strong> is required in order to implement multithreading in C since it cannot be done directly.</p> <hr></5;></pre></5;>

説明:

Javaでの接続

上記の例では、次の方法を説明します。 ロック そして ロックを解除する 競合状況から私たちを守るコードの特定の領域。 「pthread_mutex_t」 として使用されます イニシャライザ 上の例では。 「pthread_mutex_lock」 それなら 書かれた ロックしたいコードの先頭の前。その後、ロックしたいコーディングが完了します。その後、コードのロックは次のコマンドを使用して終了します。 「pthread_mutex_unlock」 ;今後は、コードがロック モードになることはありません。

食事の哲学者問題:

同期に関する典型的な問題の 1 つは、 ダイニング哲学者問題 。いくつかのプロセスに単純なリソース割り当てが必要ですが、その結果、 手詰まり または 飢え 。の 食事の哲学者の問題 は、それぞれがリソースを要求する多数のプロセスを単純に表現したものとみなすことができます。これらの各プロセスにはリソースの割り当てが必要なため、どのプロセスもスタックしたり動作を停止したりしないように、これらのリソースをすべてのプロセスに分散する必要があります。

5 人の哲学者が同じ席に座っていると仮定します。 円形のテーブル 。彼らはある時は食事をし、別の時は何かについて考えます。円卓の周りには哲学者たちが等間隔に椅子に座っています。さらに、テーブルの中央には哲学者ごとにお茶碗 1 杯と箸 5 本が置かれています。哲学者は、近くに座っている同僚と対話できないと感じたとき。

哲学者はお腹が空くと時々箸を二本手に取ります。彼女は近所の人から 2 つの箸を選び、1 つは自分に そしてもう一つは彼女に -簡単に手の届くところにあります。しかし、哲学者は決して一度に複数の箸を手に取ってはなりません。当然、隣の人が使っている箸を手に取ることはできないでしょう。

例:

例を使用して、これが C でどのように実装されるかを示してみましょう。

 #include #include #include #include #include pthread_tphilosopher[5]; pthread_mutex_tchopstick[5]; void *func(void *arg) { int n = *(int *)arg; printf(&apos;
Philosopher %d is thinking.&apos;, n); pthread_mutex_lock(&amp;chopstick[n]); pthread_mutex_lock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d is eating.&apos;, n); sleep(3); pthread_mutex_unlock(&amp;chopstick[n]); pthread_mutex_unlock(&amp;chopstick[(n + 1) % 5]); printf(&apos;
Philosopher %d Finished eating &apos;, n); return NULL; } int main() { int i, k; void *message; for (i = 0; i<5; i++) { k="pthread_mutex_init(&amp;chopstick[i]," null); if (k !="0)" printf(\'failed to initialize the mutex
\'); exit(1); } for (i="0;" i< 5; null, func, (void *)&i); printf(\'error in thread creation.
\'); &message); join thread.
\'); printf(\'mutex destroyed.
\'); return 0; < pre> <p> <strong>Output:</strong> </p> <pre> Philosopher 0 is thinking. Philosopher 1 is thinking. Philosopher 2 is thinking. Philosopher 3 is thinking. Philosopher 4 is thinking. Philosopher 0 is eating. Philosopher 1 is eating. Philosopher 2 is eating. Philosopher 3 is eating. Philosopher 4 is eating. Philosopher 0 Finished eating Philosopher 1 Finished eating Philosopher 2 Finished eating Philosopher 3 Finished eating Philosopher 4 Finished eating </pre> <p> <strong>Explanation:</strong> </p> <p> <strong> <em>Chopsticks</em> </strong> can be represented by a semaphore. Since there are <strong> <em>chopsticks</em> </strong> on the table and no philosopher has chosen one, all of the chopsticks&apos; components are first initialized to <strong> <em>1</em> </strong> . Now that <strong> <em>chopstick[i]</em> </strong> has been chosen as the first <strong> <em>chopstick. chopstick[i]</em> </strong> and <strong> <em>chopstick[(i+1)%5]</em> </strong> are subject to the first wait operation. These <strong> <em>chopsticks&apos; wait operation</em> </strong> indicates that the philosopher has picked them up. The eating process begins once the philosopher selects his <strong> <em>chopstick</em> </strong> . The signal operation is now carried out on the <strong> <em>chopsticks [i]</em> </strong> and <strong> <em>[(i+1)%5]</em> </strong> once the philosopher has finished eating. The philosopher then turns back to sleep.</p> <p>To determine whether the <strong> <em>subthread</em> </strong> has joined the main thread or not, we used the <strong> <em>pthread_join function</em> </strong> . Similarly, we have checked whether the <strong> <em>mutex</em> </strong> lock has been initialized using the <strong> <em>pthread_mutex_init</em> </strong> method.</p> <p>To initialize and verify whether the new thread was created or not, we utilized the <strong> <em>pthread_create function</em> </strong> . Similar to this, we destroyed the <strong> <em>mutex lock</em> </strong> using the <strong> <em>pthread_mutex_destroy</em> </strong> function.</p> <h2>The Producer-Consumer Problem:</h2> <p>A common issue with multithreading process synchronization is the <strong> <em>producer-consumer problem</em> </strong> . Two processes are present in it: the first is the <strong> <em>producer&apos;s process</em> </strong> , and the second is the <strong> <em>consumer&apos;s process</em> </strong> . Furthermore, it is assumed that both operations are occurring concurrently in parallel. Additionally, they are a cooperative process, which implies that they are sharing something with one another. It is important that when the buffer is <strong> <em>full</em> </strong> , the producer cannot add data. When the buffer is empty, the consumer cannot extract data from the buffer because the common buffer size between the producer and the consumer is <strong> <em>fixed</em> </strong> . The issue is stated in this way. Hence, to implement the Producer-Consumer problem and solve it, we shall employ the idea of parallel programming.</p> <p> <strong>Example:</strong> </p> <pre> #include #include int mutex = 1, full = 0, empty = 3, x = 0; int main() { int n; void producer(); void consumer(); int wait(int); int signal(int); printf(&apos;
1.producer
2.consumer
3.for exit&apos;); while (1) { printf(&apos;
 Please enter your choice:&apos;); scanf(&apos;%d&apos;, &amp;n); switch (n) { case 1: if ((mutex == 1) &amp;&amp; (empty != 0)) producer(); else printf(&apos;Oops!! the buffer is full!!&apos;); break; case 2: if ((mutex == 1) &amp;&amp; (full != 0)) consumer(); else printf(&apos;Oops!! the buffer is empty!!&apos;); break; case 3: exit(0); break; } } return 0; } int wait(int s) { return (--s); } int signal(int s) { return (++s); } void producer() { mutex = wait(mutex); full = signal(full); empty = wait(empty); x++; printf(&apos;
Item produced by the Producer %d&apos;, x); mutex = signal(mutex); } void consumer() { mutex = wait(mutex); full = wait(full); empty = signal(empty); printf(&apos;
Item consumed by the Consumer %d&apos;, x); x--; mutex = signal(mutex); } </pre> <p> <strong>Output:</strong> </p> <pre> 1. producer 2. consumer 3. for exit Please enter your choice: </pre> <p> <strong>Explanation:</strong> </p> <p>We perform two tasks. The functions <strong> <em>consumer()</em> </strong> and <strong> <em>producer()</em> </strong> indicate the status and operation of the <strong> <em>consumer</em> </strong> and <strong> <em>producer</em> </strong> . The <strong> <em>producer() method</em> </strong> will create the <strong> <em>mutex lock</em> </strong> and determine whether the buffer is <strong> <em>full</em> </strong> when it is called. When the buffer is full, nothing will be produced. If not, it will <strong> <em>create</em> </strong> , and then, after the <strong> <em>production</em> </strong> , it will put itself to sleep to unlock the <strong> <em>mutex lock</em> </strong> . Like the <strong> <em>producer</em> </strong> , the consumer first creates the <strong> <em>mutex lock</em> </strong> , checks the <strong> <em>buffer</em> </strong> , consumes the <strong> <em>product</em> </strong> , and then releases the lock before going back to sleep.</p> <p>A <strong> <em>counter (x)</em> </strong> will be used during manufacturing and will keep growing until the manufacturer produces the item. However, the consumer will make fewer of the same manufactured <strong> <em>item (x)</em> </strong> .</p> <h2>Conclusion:</h2> <p>The idea of using <strong> <em>two</em> </strong> or <strong> <em>more threads</em> </strong> to execute a program is known as <strong> <em>multithreading</em> </strong> in the C programming language. <strong> <em>Multithreading</em> </strong> allows for the simultaneous execution of several tasks. The simplest executable component of a program is a <strong> <em>thread</em> </strong> . The process is the idea that a task can be completed by breaking it up into several smaller <strong> <em>sub-processes</em> </strong> .</p> <p>The header file <strong> <em>pthread.h</em> </strong> is required in order to implement multithreading in C since it cannot be done directly.</p> <hr></5;>

説明:

セマフォで表現できます。あるので テーブルの上にあり、哲学者がどれを選んでいない場合、箸のすべてのコンポーネントは最初に次のように初期化されます。 1 。今 箸[i] 最初に選ばれました 箸。箸[i] そして 箸[(i+1)%5] 最初の待機操作の対象となります。これら 箸待ち作戦 哲学者がそれらを拾ったことを示します。哲学者が自分の食べ物を選択すると、食事のプロセスが始まります。 。シグナル操作は現在、 箸[い] そして [(i+1)%5] 哲学者が食事を終えた後。その後、哲学者は再び眠りに戻ります。

かどうかを判断するには、 サブスレッド メインスレッドに参加したかどうかに関係なく、 pthread_join関数 。同様に、 ミューテックス ロックは、を使用して初期化されました pthread_mutex_init 方法。

初期化して新しいスレッドが作成されたかどうかを確認するために、 pthread_create関数 。これと同様に、私たちは ミューテックスロック を使用して pthread_mutex_destroy 関数。

生産者と消費者の問題:

マルチスレッドプロセスの同期に関する一般的な問題は、 生産者と消費者の問題 。この中には 2 つのプロセスが存在します。1 つ目は 生産者のプロセス 、そして2番目は 消費者のプロセス 。さらに、両方の操作が並行して同時に実行されると想定されます。さらに、それらは協力的なプロセスであり、互いに何かを共有していることを意味します。バッファーが 満杯 、プロデューサーはデータを追加できません。バッファが空の場合、プロデューサとコンシューマの間の共通バッファ サイズは次のとおりであるため、コンシューマはバッファからデータを抽出できません。 修理済み 。問題はこのように述べられています。したがって、生産者と消費者の問題を実装して解決するには、並列プログラミングのアイデアを採用します。

例:

 #include #include int mutex = 1, full = 0, empty = 3, x = 0; int main() { int n; void producer(); void consumer(); int wait(int); int signal(int); printf(&apos;
1.producer
2.consumer
3.for exit&apos;); while (1) { printf(&apos;
 Please enter your choice:&apos;); scanf(&apos;%d&apos;, &amp;n); switch (n) { case 1: if ((mutex == 1) &amp;&amp; (empty != 0)) producer(); else printf(&apos;Oops!! the buffer is full!!&apos;); break; case 2: if ((mutex == 1) &amp;&amp; (full != 0)) consumer(); else printf(&apos;Oops!! the buffer is empty!!&apos;); break; case 3: exit(0); break; } } return 0; } int wait(int s) { return (--s); } int signal(int s) { return (++s); } void producer() { mutex = wait(mutex); full = signal(full); empty = wait(empty); x++; printf(&apos;
Item produced by the Producer %d&apos;, x); mutex = signal(mutex); } void consumer() { mutex = wait(mutex); full = wait(full); empty = signal(empty); printf(&apos;
Item consumed by the Consumer %d&apos;, x); x--; mutex = signal(mutex); } 

出力:

 1. producer 2. consumer 3. for exit Please enter your choice: 

説明:

キツネかオオカミ

私たちは 2 つのタスクを実行します。機能 消費者() そして プロデューサー() のステータスと動作を示します。 消費者 そして プロデューサー 。の プロデューサー() メソッド を作成します ミューテックスロック バッファが 満杯 呼ばれたとき。バッファがいっぱいになると、何も生成されません。そうでない場合は、そうなります 作成する 、その後、 生産 、ロックを解除するために自らをスリープ状態にします。 ミューテックスロック 。以下のような プロデューサー 、消費者は最初に ミューテックスロック 、チェックします バッファ を消費します。 製品 、スリープに戻る前にロックを解除します。

カウンター (x) 製造中に使用され、メーカーが商品を生産するまで成長し続けます。しかし、消費者が同じ製品を作ることは少なくなります。 項目 (x)

結論:

使うという発想 または さらに多くのスレッド プログラムを実行することは、として知られています マルチスレッド C プログラミング言語で。 マルチスレッド化 複数のタスクを同時に実行できます。プログラムの最も単純な実行可能なコンポーネントは、 。プロセスとは、タスクをいくつかの小さなタスクに分割することで完了できるという考え方です。 サブプロセス

ヘッダーファイル pthread.h C でマルチスレッドを実装するには、直接実行できないため、これが必要です。