logo

MULTITREADING I C

Introduksjon:

I C, begrepet 'flertråder' beskriver bruken av mange tråder samtidig. Hver tråd gjør en annen oppgave . På grunn av den samtidige naturen til multithreading, kan mange oppgaver utføres samtidig. I tillegg, flertråding reduserer CPUs ressursbruk . Det er to kategorier av multitasking: prosessbasert og trådbasert . Når noe beskrives som multithreading, betyr det at minst to eller kanskje flere tråder kjører i samme prosess samtidig. Vi må først forstå hva en tråd og en prosess er for å forstå multithreading i C. La oss se på disse emnene for å få en bedre forståelse.

java type variabel

Hva er prosesser og tråder?

EN tråd er den grunnleggende bygning blokkere av enhver prosess utførelse. Et program er bygd opp av flere prosesser, og hver prosess er bygd opp av tråder, som er mye mer grunnleggende enheter. Derfor kan tråden betraktes som den grunnleggende byggesteinen i en prosess eller den enklere enheten som i fellesskap bestemmer CPU-utnyttelsen.

Følgende elementer er inkludert i en tråd:

Tråd-ID:

Det er en spesiell tråd-ID som genereres på tidspunktet for tråddannelse og beholdes i den spesifikke trådens varighet.

Programteller:

Det er en verdi som maskinvare laster .

Et registrert sett:

Det er en samling av felles registre .

En stabel:

Det er en rest av det spesifikk tråd .

I tillegg, hvis to tråder fungerer samtidig i samme prosess, deler de kode , dataseksjoner , og andre operativsystemressurser som fil åpnes og signaler . En tungvektsprosess, en type konvensjonell prosess, kan kontrollere én tråd. Imidlertid har en multi-thread of control kapasitet til å åpne og utføre flere oppgaver samtidig. Systemet blir betydelig mer effektivt som følge av bruk av tråder, og derfor er de nyttige.

Skillet mellom enkelt og flertråding i C er forklart. Først av alt er det en én-tråds prosess . Som et resultat, hele blokken-inkludert kode, data, etc.-betraktes som én prosess, og den prosessen har kun én tråd. Det betyr at denne teknikken vil fullføre bare én oppgave om gangen. Men det er en flertrådsprosess som står i motsetning til dette. Det er aktiviteter som kode, stabel, data , og filer også, men de utføres av flere tråder, som hver har sin egen stabel og registre. Gitt at mange oppgaver kan fullføres på en gang i denne situasjonen, er prosessen kjent som en flertrådsprosess .

Tråden kommer i to varianter:

Tråd på brukernivå:

Det er på brukernivå, som navnet tilsier. Kjernen får ikke tilgang til dataene sine.

Tråd på kjernenivå

Typen tråd refererer til trådens forhold til kjernen og operativsystemet til systemet.

Prosess- Serien av trinn som er tatt for å gjennomføre et program kan refereres til som prosess . Et program kjøres ikke umiddelbart når det kjøres. Det er brutt ned i noen få grunnleggende trinn som utføres sekvensielt på en organisert måte for å føre til utførelse av en prosess til slutt.

En prosess som har blitt brutt ned i mindre trinn omtales som en 'klone- eller barneprosess', mens den opprinnelige prosessen blir referert til som 'foreldre' prosess . I minnet bruker hver prosess en viss mengde plass som ikke deles med noen andre prosesser.

En prosedyre går gjennom noen stadier før utførelse.

NY-

I denne situasjonen er en ny prosess generert .

KLAR-

Når en prosess er forberedt og venter på at en prosessor skal tildeles, er den i denne tilstanden.

LØPING-

Når prosessen er aktiv, er det staten.

sjakal vs ulv

VENTER-

Når en prosess er i denne tilstanden, er det noe venter å skje.

AVSLUTTET-

Det er tilstanden prosedyren utføres i.

Hvorfor er C flertrådet?

Multithreading i C-ideen kan utnyttes gjennom parallellisme for å forbedre en applikasjonens funksjonalitet . Tenk på tilfellet der du har flere faner åpne i et nettleservindu. Deretter fungerer hver fane samtidig og kan bli referert til som en Tråd . Forutsatt at vi bruker Microsoft Excel , en tråd vil klare tekstformatering , og en tråd vil håndtere innspill . Derfor gjør Cs multithreading-funksjon det enkelt å utføre flere oppgaver samtidig. Opprettelsen av en tråd er betydelig raskere. Kontekstoverføringen på tvers av tråder skjer raskere. I tillegg kan kommunikasjon mellom tråder gjøres raskere, og trådavslutning er enkel.

Hvordan skrive C-programmer for multithreading?

Selv om multithreading-applikasjoner ikke er innebygd i C-språket, er det mulig avhengig av operativsystemet. De threads.h standardbibliotek brukes til å implementere multithreading-ideen i C . Imidlertid er det foreløpig ingen kompilator som kan gjøre dette. Vi må bruke plattformspesifikke implementeringer, for eksempel 'POSIX' trådbibliotek, ved å bruke overskriftsfilen pthread.h , hvis vi ønsker å bruke multithreading i C. 'Pthreads' er et annet navn for dette. EN POSIX tråd kan opprettes på følgende måter:

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

I dette tilfellet, Pthread_create oppretter en ny tråd for å gjøre tråden kjørbar. Den lar deg implementere multithreading i C så mange ganger du vil i koden din. Parametrene og deres beskrivelser fra tidligere er listet opp her.

tråd:

Det er en entallsidentifikasjon at delprosess returnerer .

attr:

Når vi vil sette trådattributter, bruker vi dette ugjennomsiktig attributt .

start_rutine:

Når start_rutine er generert, vil tråden kjøre en rutine.

arg:

Parameteren som start_rutine mottar. NULL vil bli brukt hvis ingen argumenter er gitt.

programvaretesting og -typer

Visse C multithreading eksempler

Her er noen eksempler på problemer med flere tråder i C.

1. Leser-skribent-utgaven

Et vanlig operativsystemproblem med prosesssynkronisering er leser/skribent problem . Anta at vi har en database som Lesere og Forfattere , to forskjellige brukerkategorier, har tilgang. Lesere er de eneste som kan lese databasen, mens Forfattere er de eneste som kan lese databasen og oppdatere den også. La oss bruke IRCTC som et enkelt eksempel. Hvis vi ønsker å sjekke statusen til en bestemt tognummer , skriv inn tognummeret i systemet for å se relevant toginformasjon. Kun informasjonen som finnes på nettsiden vises her. Lesoperatoren er denne. Men hvis vi ønsker å reservere en billett, må vi fylle ut billettbestillingsskjemaet med detaljer som navn, alder og så videre. Så vi utfører en skriveoperasjon her. Det vil bli gjort noen justeringer IRCTC database .

Problemet er at flere personer samtidig prøver å få tilgang til IRCTC database . De kan være en forfatter eller a leser . Problemet oppstår hvis en leser allerede bruker databasen og en forfatter får tilgang til den samtidig for å jobbe med de samme dataene. Et annet problem oppstår når en forfatter bruker en database, og en leser får tilgang til samme informasjon som databasen. For det tredje er det en vanskelighet når en forfatter oppdaterer databasen mens en annen forsøker å oppdatere data på samme database. Det fjerde scenariet oppstår når to lesere prøver å hente det samme materialet. Alle disse problemene oppstår hvis leseren og forfatteren bruker samme databasedata.

Semafor er en metode som brukes for å løse dette problemet. La oss se på en illustrasjon av hvordan du bruker dette problemet.

Leserprosess:

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

Forklaring:

I denne koden har vi de delte variabeldataene og lesertall rc . De wrt tilstand variabelen brukes til å begrense tilgangen til forfatterprosess , og mutex brukes til å garantere gjensidig utestenging for tilgang til delte data.

Leserprosessen er representert ved reader() funksjon . De lesertall (rc) økes før man oppnår mutex lås . Det bruker pthread_cond_wait() å vente på wrt tilstand variabel hvis det er første leser (rc == 1) . Som et resultat vil forfattere bli forhindret fra å skrive før alle lesere har fullført.

Leserprosessen sjekker om det var siste leser (rc == 0) og senker leseren telle (rc--) etter å ha lest de delte dataene. Hvis det var, pthread_cond_signal() signaliserer wrt tilstand variabel for å la ventende skriveprosesser fortsette.

Bruker pthread_create() og pthread_join() funksjoner , vi ny og bli med flere lesertråder i hovedfunksjon . En individuell ID tildeles hver lesertråd for å identifisere formål.

Forfatterprosess:

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

I eksemplet ovenfor, det samme som leserprosess , en operasjon kjent som venteoperasjonen utføres på 'wrt' når en bruker ønsker å få tilgang til dataene eller objektet. Etter det vil ikke den nye brukeren få tilgang til objektet. Og når brukeren er ferdig med å skrive, utføres en ny signaloperasjon på wrt .

2. låse og låse opp problem:

Ideen om en mutex brukes i multithreading i C for å garantere at det ikke vil være en løpstilstand mellom tråder . Når flere tråder begynner å behandle de samme dataene samtidig, kalles denne omstendigheten Racing . Men hvis disse omstendighetene eksisterer, må vi. Vi bruker mutex sin lås() og unlock() funksjoner for å sikre en bestemt kodedel for en bestemt tråd. Slik at en annen tråd ikke kan begynne å utføre den samme operasjonen. De 'kritisk del/region' er navnet gitt til dette beskyttede kodeområdet. Før vi bruker de delte ressursene setter vi opp mye i et bestemt område, og når vi er ferdige med å bruke dem, låser vi dem opp igjen.

La oss undersøke funksjonen til mutex for låsing og opplåsing i multithreading i C:

Eksempel:

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

Forklaring:

programvaretesting og -typer

I dette eksemplet ovenfor forklarer vi hvordan vi låse og låse opp en viss koderegion som skjermer oss fra racingsituasjonen. 'pthread_mutex_t' brukes som en initialiserer i eksemplet ovenfor. 'pthread_mutex_lock' er da skrevet før begynnelsen av koden som vi ønsker å låse. Kodingen som vi ønsker å låse er ferdig etter det. Etter det avsluttes låsingen av koden vha 'pthread_mutex_unlock' ; fremover vil ingen kode være i låsemodus.

Spisefilosofproblemet:

Et av de klassiske problemene med synkronisering er spisefilosof problem . Enkel ressursallokering for flere prosesser er nødvendig, men bør ikke resultere i en fastlåst situasjon eller sult . De serveringsfilosofproblem kan sees på som en enkel representasjon av en rekke prosesser, som hver for seg krever ressurser. Siden hver av disse prosessene krever en ressursallokering, er det nødvendig å distribuere disse ressursene på tvers av alle prosessene slik at ingen prosess noen gang blir sittende fast eller slutter å fungere.

Anta at det er fem filosofer som sitter ved en sirkelformet bord . De spiser på et tidspunkt og grubler over noe på et annet. Rundt det runde bordet er filosofene jevnt fordelt på stolene. I tillegg er det en skål med ris og fem spisepinner til hver filosof midt på bordet. Når filosofen føler at hun ikke kan samhandle med kollegene sine som sitter i nærheten.

En filosof tar av og til opp to spisepinner når hun blir sulten. Hun velger to spisepinner fra naboene - en på henne venstre og en på henne Ikke sant - som er innen rekkevidde. Men filosofen bør aldri plukke opp mer enn én spisepinne på en gang. Hun vil åpenbart ikke klare å ta opp spisepinnen som naboen bruker.

Eksempel:

La oss bruke et eksempel for å demonstrere hvordan dette er implementert i 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;>

Forklaring:

java tostring-metoden

Spisepinner kan representeres av en semafor. Siden det er spisepinner på bordet og ingen filosof har valgt en, initialiseres først alle spisepinnenes komponenter til 1 . Nå som spisepinne[i] er valgt som den første spisepinne. spisepinne[i] og spisepinne[(i+1)%5] er gjenstand for den første venteoperasjonen. Disse spisepinners venteoperasjon indikerer at filosofen har plukket dem opp. Spiseprosessen begynner når filosofen velger sin spisepinne . Signaloperasjonen utføres nå på spisepinner [i] og [(i+1)%5] når filosofen er ferdig med å spise. Filosofen går så i dvale igjen.

For å avgjøre om undertråd har sluttet seg til hovedtråden eller ikke, vi brukte den pthread_join funksjon . På samme måte har vi sjekket om mutex låsen er initialisert ved hjelp av pthread_mutex_init metode.

For å initialisere og bekrefte om den nye tråden ble opprettet eller ikke, brukte vi pthread_create-funksjonen . I likhet med dette ødela vi mutex lås bruker pthread_mutex_destroy funksjon.

Produsent-forbrukerproblemet:

Et vanlig problem med flertrådsprosesssynkronisering er produsent-forbruker problem . To prosesser er til stede i den: den første er produsentens prosess , og den andre er forbrukerens prosess . Videre antas det at begge operasjonene skjer parallelt. I tillegg er de en samarbeidsprosess, som innebærer at de deler noe med hverandre. Det er viktig at når bufferen er full , kan ikke produsenten legge til data. Når bufferen er tom, kan ikke forbrukeren trekke ut data fra bufferen fordi den felles bufferstørrelsen mellom produsent og forbruker er det fikset . Problemstillingen er formulert på denne måten. Derfor, for å implementere produsent-forbruker-problemet og løse det, skal vi bruke ideen om parallell programmering.

Eksempel:

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

Produksjon:

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

Forklaring:

Vi utfører to oppgaver. Funksjonene forbruker() og produsent() angi status og drift av forbruker og produsent . De producer()-metoden vil lage mutex lås og bestemme om bufferen er full når det kalles. Når bufferen er full, vil ingenting bli produsert. Hvis ikke, vil det gjøre det skape , og deretter, etter produksjon , vil den sette seg selv i dvale for å låse opp mutex lås . Som produsent , forbrukeren oppretter først mutex lås , sjekker buffer , forbruker produkt , og slipper deretter låsen før du går i dvale igjen.

EN teller (x) vil bli brukt under produksjon og vil fortsette å vokse til produsenten produserer varen. Imidlertid vil forbrukeren lage færre av det samme produsert element (x) .

Konklusjon:

Ideen om å bruke to eller flere tråder å kjøre et program er kjent som flertråding i programmeringsspråket C. Multithreading gir mulighet for samtidig utførelse av flere oppgaver. Den enkleste kjørbare komponenten i et program er en tråd . Prosessen er ideen om at en oppgave kan fullføres ved å dele den opp i flere mindre delprosesser .

Overskriftsfilen pthread.h er nødvendig for å implementere multithreading i C siden det ikke kan gjøres direkte.