logo

DAUDZVIEDIENI C

Ievads:

C valodā termins 'daudzpavedienu' apraksta daudzu izmantošanu pavedieni vienlaikus. Katrs pavediens veic a atšķirīgs uzdevums . Daudzpavedienu vienlaicīgas rakstura dēļ daudzus uzdevumus var veikt vienlaikus. Turklāt daudzpavedienu samazina CPU resursu lietojums . Ir divas vairākuzdevumu kategorijas: uz procesu balstīta un uz pavedieniem balstīta . Ja kaut kas tiek aprakstīts kā vairākpavedienu, tas nozīmē, ka vismaz divi vai, iespējams, vairāki pavedieni darbojas vienā un tajā pašā procesā. Vispirms mums ir jāsaprot, kas ir pavediens un process, lai izprastu vairākpavedienu izmantošanu C valodā. Apskatīsim šos priekšmetus, lai iegūtu labāku izpratni.

java dinamiskais masīvs

Kas ir procesi un pavedieni?

A pavediens ir fundamentāla ēka bloķēt par jebkura procesa izpildi. Programma sastāv no vairākiem procesiem, un katrs process sastāv no pavedieniem, kas ir daudz vairāk pamata vienības. Tāpēc pavedienu var uzskatīt par procesa pamatelementu vai vienkāršāku vienību, kas kopīgi nosaka CPU izmantošanu.

Pavedienā ir iekļauti šādi vienumi:

Pavediena ID:

Tas ir īpašs pavediena ID kas tiek ģenerēts pavediena veidošanas laikā un tiek saglabāts konkrētā pavediena darbības laikā.

Programmu skaitītājs:

Tā ir vērtība, ko aparatūras slodzes .

Reģistrēts komplekts:

Tā ir kolekcija kopīgie reģistri .

Kaudzīte:

Tā ir palieka no tā konkrēts pavediens .

Turklāt, ja divi pavedieni darbojas vienlaikus vienā un tajā pašā procesā, tie tiek koplietoti kodu , datu sadaļas un citus operētājsistēmas resursus, piemēram, failu atveras un signāliem . Smagsvara process, parastā procesa veids, var kontrolēt vienu pavedienu. Tomēr vairāku pavedienu vadīkla spēj vienlaikus atvērt un veikt vairākus uzdevumus. Sistēma kļūst ievērojami efektīvāka, izmantojot pavedienus, tāpēc tie ir noderīgi.

Atšķirība starp viens un daudzpavedienu C ir izskaidrots. Pirmkārt, tas ir a viena vītnes process . Tā rezultātā viss bloks, ieskaitot kods, dati, utt. — tiek uzskatīts par vienu procesu, un šim procesam ir tikai viens pavediens. Tas nozīmē, ka šī tehnika vienlaikus izpildīs tikai vienu uzdevumu. Bet ir a daudzpavedienu process kas ir pretstatā tam. Ir tādas aktivitātes kā kods, kaudze, dati , un failus kā arī, bet tos veic vairāki pavedieni, kuriem katram ir savs steks un reģistri. Ņemot vērā, ka šajā situācijā vienlaikus var veikt vairākus uzdevumus, process ir pazīstams kā a daudzpavedienu process .

Vītnei ir divas šķirnes:

Pavediens lietotāja līmenī:

Tas ir lietotāja līmenī, kā norāda nosaukums. Kodolam netiek piešķirta piekļuve tā datiem.

java lambda

Pavediens kodola līmenī

Vītnes veids attiecas uz pavediena saistību ar kodolu un sistēmas operētājsistēmu.

Process- Programmas izpildei veikto darbību virkni var saukt par process . Programma netiek nekavējoties izpildīta, kad tā tiek palaista. Tas ir sadalīts dažos pamata soļos, kas tiek veikti secīgi organizētā veidā, lai galu galā novestu pie procesa izpildes.

Procesu, kas ir sadalīts mazākos posmos, sauc par a “klona vai bērna process”, kamēr sākotnējais process tiek saukts par “vecāku” process . Atmiņā katrs process izmanto noteiktu vietas daudzumu, kas netiek koplietots ar citiem procesiem.

Pirms izpildes procedūra iziet dažus posmus.

JAUNUMS-

Šajā situācijā ir jauns process radīts .

GATAVS-

Kad process ir sagatavots un gaida procesora piešķiršanu, tas ir šajā stāvoklī.

SKREJ-

Kad process ir aktīvs, tas ir stāvoklis.

GAIDA-

Kad process ir šādā stāvoklī, kaut kas ir gaida notikt.

BEIGTS-

Tā ir valsts, kurā tiek veikta procedūra.

Kāpēc C ir daudzpavedienu?

Daudzpavedienu veidošana C idejā var izmantot paralēlismu, lai uzlabotu lietojumprogrammas funkcionalitāte . Apsveriet gadījumu, kad pārlūkprogrammas logā ir atvērtas vairākas cilnes. Pēc tam katra cilne darbojas vienlaikus un var tikt saukta par a Pavediens . Pieņemot, ka lietojam Microsoft Excel , tiks pārvaldīts viens pavediens teksta formatēšana , un viens pavediens būs rokturis ievade . Tāpēc C daudzpavedienu funkcija ļauj vienkārši veikt vairākus uzdevumus vienlaikus. Vītnes izveide ir ievērojami ātrāka. Konteksta pārsūtīšana starp pavedieniem notiek ātrāk. Turklāt saziņu starp pavedieniem var izveidot ātrāk, un pavedienu pārtraukšana ir vienkārša.

Kā uzrakstīt C programmas daudzpavedienu veidošanai?

Lai gan daudzpavedienu lietojumprogrammas nav iebūvētas C valodā, tas ir iespējams atkarībā no operētājsistēmas. The threads.h standarta bibliotēka tiek izmantots, lai īstenotu daudzpavedienu ideju C . Tomēr pašlaik nav neviena kompilatora, kas to varētu izdarīt. Mums ir jāizmanto platformai specifiskas ieviešanas, piemēram, 'POSIX' pavedienu bibliotēka, izmantojot galvenes failu pthread.h , ja mēs vēlamies izmantot daudzpavedienu C. 'pavedieni' ir cits nosaukums šim. A POSIX pavedienu var izveidot šādos veidos:

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

Šajā gadījumā, Pthread_create izveido jaunu pavedienu, lai padarītu pavedienu izpildāmu. Tas ļauj ieviest daudzpavedienu C valodā tik reižu, cik vēlaties savā kodā. Šeit ir uzskaitīti iepriekšējie parametri un to apraksti.

izņēmums mest java

pavediens:

Tas ir vienskaitļa identifikācija ka apakšprocess atgriežas .

att:

Kad mēs vēlamies iestatīt pavedienu atribūtus, mēs izmantojam šo necaurspīdīgs atribūts .

start_ruutine:

Kad sākuma_rutīna tiek ģenerēts, pavediens darbosies pēc rutīnas.

arg:

Parametrs, kas sākuma_rutīna saņem. NULL tiks izmantots, ja nav sniegti argumenti.

Daži C daudzpavedienu piemēri

Šeit ir daži piemēri daudzpavedienu problēmām programmā C.

1. Lasītāja un rakstnieka problēma

Izplatīta operētājsistēmas problēma ar procesu sinhronizāciju ir lasītāja/rakstītāja problēma . Pieņemsim, ka mums ir datu bāze, kas Lasītāji un Rakstnieki , var piekļūt divām dažādām lietotāju kategorijām. Lasītāji ir vienīgie, kas var lasīt datu bāzē, turpretim Rakstnieki ir vienīgie, kas var lasīt datubāzi un to arī atjaunināt. Izmantosim IRCTC kā vienkāršs piemērs. Ja vēlamies pārbaudīt konkrēta statusu vilciena numurs , vienkārši ievadiet vilciena numuru sistēmā, lai skatītu attiecīgo vilciena informāciju. Šeit tiek rādīta tikai informācija, kas ir pieejama vietnē. Lasīšanas operators ir šāds. Tomēr, ja vēlamies rezervēt biļeti, mums ir jāaizpilda biļešu rezervēšanas veidlapa, norādot tādu informāciju kā mūsu vārds, vecums un tā tālāk. Tātad, mēs šeit veiksim rakstīšanas darbību. Tiks veikti daži pielāgojumi IRCTC datu bāze .

Problēma ir tāda, ka vairāki cilvēki vienlaikus mēģina piekļūt IRCTC datu bāze . Tie varētu būt a rakstnieks vai a lasītājs . Problēma rodas, ja lasītājs jau izmanto datu bāzi un rakstītājs tai vienlaikus piekļūst, lai strādātu ar tiem pašiem datiem. Cita problēma rodas, ja rakstītājs izmanto datu bāzi un lasītājs piekļūst tai pašai informācijai kā datu bāzei. Treškārt, rodas grūtības, ja viens rakstītājs atjaunina datu bāzi, bet cits mēģina atjaunināt datus tajā pašā datubāzē. Ceturtais scenārijs notiek, kad divi lasītāji mēģina izgūt vienu un to pašu materiālu. Visas šīs problēmas rodas, ja lasītājs un rakstītājs izmanto vienus un tos pašus datu bāzes datus.

Semafors ir metode, kas tiek izmantota šīs problēmas risināšanai. Apskatīsim ilustrāciju, kā izmantot šo problēmu.

Lasīšanas process:

 #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;>

Paskaidrojums:

Šajā kodā mums ir koplietotie mainīgie dati un lasītāju skaits rc . The wrt stāvoklis mainīgais tiek izmantots, lai ierobežotu piekļuvi rakstīšanas process , un mutex tiek izmantots, lai garantētu savstarpēju izslēgšanu attiecībā uz piekļuvi koplietotajiem datiem.

Lasīšanas procesu attēlo lasītāja() funkcija . The lasītāju skaits (rc) tiek palielināts, pirms tiek sasniegts mutex slēdzene . Tā izmanto pthread_cond_wait() gaidīt uz wrt stāvoklis mainīgais, ja tas ir pirmais lasītājs (rc == 1) . Tā rezultātā rakstītāji nevarēs rakstīt, kamēr visi lasītāji nebūs pabeiguši.

Lasīšanas process pārbauda, ​​vai tas bija pēdējais lasītājs (rc == 0) un pazemina lasītāju skaits (rc--) pēc kopīgoto datu izlasīšanas. Ja tā būtu, pthread_cond_signal() signalizē wrt stāvoklis mainīgais, lai turpinātu gaidīšanas rakstīšanas procesus.

Izmantojot pthread_create() un pthread_join() funkcijas , mēs jauns un pievienoties vairāki lasītāju pavedieni galvenā() funkcija . Katram lasītāja pavedienam tiek piešķirts individuāls ID identifikācijas nolūkos.

Rakstīšanas process:

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

Iepriekš minētajā piemērā tas pats, kas lasītāja process , tiek veikta darbība, kas pazīstama kā gaidīšanas darbība 'wrt' kad lietotājs vēlas piekļūt datiem vai objektam. Pēc tam jaunais lietotājs nevarēs piekļūt objektam. Kad lietotājs ir beidzis rakstīt, tiek veikta cita signāla darbība wrt .

2. bloķēšanas un atbloķēšanas problēma:

Ideja par a mutex tiek izmantots daudzpavedienu veidošanā C, lai garantētu, ka nebūs a sacensību stāvoklis starp pavedieni . Ja vairāki pavedieni sāk apstrādāt vienus un tos pašus datus vienlaikus, šis apstāklis ​​tiek saukts par sacīkstes . Tomēr, ja šādi apstākļi pastāv, mums tas ir jādara. Mēs izmantojam mutex atslēga () un unlock() funkcijas lai nodrošinātu noteiktu koda sadaļu konkrētam pavedienam. Tā, ka cits pavediens nevar sākt veikt to pašu darbību. The 'kritiskā sadaļa/reģions' ir šī aizsargājamā koda apgabala nosaukums. Pirms koplietojamo resursu izmantošanas mēs noteiktā apgabalā iestatījām daudz, un, kad esam pabeiguši to izmantošanu, mēs tos vēlreiz atbloķējam.

Apskatīsim mutex darbību bloķēšanai un atbloķēšanai daudzpavedienos C:

Piemērs:

 #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;>

Paskaidrojums:

kāds ir mana monitora izmērs

Šajā iepriekš minētajā piemērā mēs izskaidrojam, kā mēs slēdzene un atbloķēt noteikts koda reģions, kas mūs pasargā no sacīkšu situācijas. 'pthread_mutex_t' tiek izmantots kā inicializators iepriekš minētajā piemērā. 'pthread_mutex_lock' ir tad rakstīts pirms koda sākuma, kuru vēlamies bloķēt. Pēc tam tiek pabeigta kodēšana, kuru vēlamies bloķēt. Pēc tam koda bloķēšana tiek pārtraukta, izmantojot 'pthread_mutex_unlock' ; turpinot, neviens kods nebūs bloķēšanas režīmā.

Ēdināšanas filozofa problēma:

Viena no klasiskajām sinhronizācijas problēmām ir ēdināšanas filozofa jautājums . Ir nepieciešama vienkārša resursu piešķiršana vairākiem procesiem, taču tai nevajadzētu izraisīt a strupceļš vai izsalkums . The ēdināšanas filozofa problēma var uzskatīt par vienkāršu vairāku procesu attēlojumu, no kuriem katrs prasa resursus. Tā kā katram no šiem procesiem ir nepieciešama resursu piešķiršana, šie resursi ir jāsadala pa visiem procesiem, lai neviens process neiestrēgtu vai nepārstātu darboties.

Pieņemsim, ka pie a sēž pieci filozofi apļa formas galds . Viņi vienā brīdī ēd, bet citā par kaut ko domā. Ap apaļo galdu filozofi ir vienmērīgi izvietoti uz krēsliem. Turklāt katram filozofam galda vidū ir bļoda ar rīsiem un pieci irbulīši. Kad filozofei šķiet, ka viņa nevar sazināties ar kolēģiem, kas sēž tuvumā.

Filozofs ik pa laikam paņem divus irbulīšus, kad kļūst izsalcis. Viņa izvēlas divus irbulīšus no kaimiņiem — vienu uz viņas pa kreisi un viens uz viņas pa labi - kas ir viegli sasniedzami. Taču filozofam nekad nevajadzētu uzreiz paņemt vairāk par vienu irbulīti. Viņa acīmredzot nespēs paņemt irbulīti, ko izmanto kaimiņš.

Piemērs:

Izmantosim piemēru, lai parādītu, kā tas tiek īstenots 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;>

Paskaidrojums:

Irbulīši var attēlot ar semaforu. Tā kā ir irbulīši uz galda un neviens filozofs to nav izvēlējies, visi irbulīša komponenti vispirms tiek inicializēti, lai 1 . Tagad tas irbulīša [i] ir izvēlēts kā pirmais irbulītis. irbulīša [i] un irbulīša [(i+1)%5] uz tiem attiecas pirmā gaidīšanas darbība. Šie irbulīšu gaidīšanas operācija norāda, ka filozofs tos ir paņēmis. Ēšanas process sākas, kad filozofs izvēlas savu irbulītis . Signāla darbība tagad tiek veikta uz irbulīši [i] un [(i+1)%5] kad filozofs ir beidzis ēst. Pēc tam filozofs atgriežas miegā.

Lai noteiktu, vai apakšpavediens ir pievienojies galvenajam pavedienam vai nē, mēs izmantojām pthread_join funkcija . Tāpat mēs esam pārbaudījuši, vai mutex slēdzene ir inicializēta, izmantojot pthread_mutex_init metodi.

Lai inicializētu un pārbaudītu, vai jaunais pavediens ir izveidots vai nē, mēs izmantojām funkcija pthread_create . Līdzīgi šim mēs iznīcinājām mutex slēdzene izmantojot pthread_mutex_destroy funkciju.

romiešu cipari 1100

Ražotāja un patērētāja problēma:

Izplatīta problēma ar daudzpavedienu procesa sinhronizāciju ir ražotāja-patērētāja problēma . Tajā notiek divi procesi: pirmais ir ražotāja process , un otrais ir patērētāja process . Turklāt tiek pieņemts, ka abas darbības notiek vienlaikus paralēli. Turklāt tie ir sadarbības process, kas nozīmē, ka viņi kaut ko dalās viens ar otru. Ir svarīgi, ka tad, kad buferis ir pilns , ražotājs nevar pievienot datus. Kad buferis ir tukšs, patērētājs nevar iegūt datus no bufera, jo kopējais bufera lielums starp ražotāju un patērētāju ir fiksēts . Jautājums ir izklāstīts šādā veidā. Līdz ar to, lai realizētu un atrisinātu ražotāja-patērētāja problēmu, tiks izmantota paralēlās programmēšanas ideja.

Piemērs:

 #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); } 

Izvade:

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

Paskaidrojums:

Mēs veicam divus uzdevumus. Funkcijas patērētājs () un ražotājs () norāda statusu un darbību patērētājs un ražotājs . The ražotāja() metode izveidos mutex slēdzene un noteikt, vai buferis ir pilns kad to sauc. Kad buferis būs pilns, nekas netiks ražots. Ja nē, tad būs izveidot , un pēc tam, pēc ražošanu , tas aizmigs, lai atbloķētu mutex slēdzene . Kā ražotājs , patērētājs vispirms izveido mutex slēdzene , pārbauda buferis , patērē produkts , un pēc tam atlaiž slēdzeni pirms atgriešanās gulēt.

A skaitītājs (x) tiks izmantots ražošanas laikā un turpinās augt, līdz ražotājs ražos preci. Tomēr patērētājs ražos mazāk tādu pašu izstrādājumu vienums (x) .

Secinājums:

Ideja par lietošanu divi vai vairāk pavedienu Programmas izpilde ir pazīstama kā daudzpavedienu C programmēšanas valodā. Daudzpavedienu veidošana ļauj vienlaikus veikt vairākus uzdevumus. Vienkāršākā programmas izpildāmā sastāvdaļa ir a pavediens . Process ir ideja, ka uzdevumu var pabeigt, sadalot to vairākos mazākos apakšprocesi .

Galvenes fails pthread.h ir nepieciešams, lai ieviestu daudzpavedienu izveidošanu programmā C, jo to nevar izdarīt tieši.