logo

VIŠENITNOST U C

Uvod:

U C, pojam 'višenitnost' opisuje korištenje brojnih niti istovremeno. Svaka nit radi a drugačiji zadatak . Zbog istodobne prirode višenitnosti, mnogi se zadaci mogu izvršiti odjednom. Dodatno, višenitnosti smanjuje Upotreba resursa CPU-a . Postoje dvije kategorije multitaskinga: temeljen na procesu i na bazi niti . Kada se nešto opisuje kao višenitnost, to znači da barem dvije ili možda više niti rade u istom procesu odjednom. Prvo moramo razumjeti što su nit i proces kako bismo razumjeli višenitnost u C-u. Pogledajmo ove teme kako bismo bolje razumjeli.

sql count distinct

Što su procesi i niti?

A nit je temeljna zgrada blok izvršenja bilo kojeg procesa. Program se sastoji od nekoliko procesa, a svaki proces se sastoji od niti, koje su puno osnovnije jedinice. Stoga se nit može smatrati temeljnim građevnim blokom procesa ili jednostavnijom jedinicom koja zajednički određuje korištenje CPU-a.

Sljedeće stavke su uključene u nit:

ID niti:

To je poseban ID niti koji se stvara u vrijeme formiranja niti i zadržava tijekom trajanja te specifične niti.

Brojač programa:

To je vrijednost koju hardverska opterećenja .

Registrirani set:

To je zbirka zajednički registri .

Stog:

To je ostatak toga specifična nit .

Osim toga, ako dvije niti rade istovremeno u istom procesu, one dijele kodirati , odjeljci podataka i drugi resursi operativnog sustava poput datoteke otvara i signale . Teški proces, tip konvencionalnog procesa, može kontrolirati jednu nit. Međutim, kontrola s više niti ima sposobnost otvaranja i izvršavanja više zadataka istovremeno. Sustav postaje znatno učinkovitiji korištenjem niti, zbog čega su korisne.

Razlika između singl i višenitnosti u C je objašnjeno. Prije svega, to je a proces s jednom niti . Kao rezultat toga, cijeli blok - uključujući kod, podaci, itd.-smatra se kao jedan proces, a taj proces ima samo jednu nit. To znači da će ova tehnika izvršiti samo jedan zadatak odjednom. Ali postoji višenitni proces koji stoji nasuprot ovome. Postoje aktivnosti poput kod, stog, podaci , i datoteke također, ali ih izvodi nekoliko niti, od kojih svaka ima svoj vlastiti stog i registre. S obzirom da se brojni zadaci mogu dovršiti odjednom u ovoj situaciji, proces je poznat kao a višenitni proces .

Konac dolazi u dvije varijante:

Nit na korisničkoj razini:

To je na korisničkoj razini, kao što naziv implicira. Kernel nema pristup svojim podacima.

Nit na razini jezgre

Vrsta niti odnosi se na odnos niti prema jezgri i operativnom sustavu sustava.

Postupak- Niz koraka poduzetih za provedbu programa može se nazvati postupak . Program se ne izvršava odmah kada se pokrene. Raščlanjuje se na nekoliko osnovnih koraka koji se provode uzastopno na organiziran način kako bi na kraju doveli do izvršenja procesa.

Proces koji je podijeljen na manje korake naziva se a 'klon ili podređeni proces', dok se izvorni proces naziva 'roditeljski' proces . U memoriji svaki proces koristi određenu količinu prostora koji se ne dijeli s drugim procesima.

Procedura prolazi kroz nekoliko faza prije izvršenja.

NOVI-

U ovoj situaciji, novi proces je generiran .

SPREMAN-

Kada je proces pripremljen i čeka na dodjelu procesora, on je u ovom stanju.

TRČANJE-

Kada je proces aktivan, to je stanje.

ČEKANJE-

js postavljeno

Kada je proces u ovom stanju, nešto jest čekajući dogoditi se.

RASKINUTO-

sortiranje selekcije u Javi

To je stanje u kojem se postupak provodi.

Zašto je C višenitni?

Višenitnost u C ideja može se iskoristiti kroz paralelizam za poboljšanje an funkcionalnost aplikacije . Razmotrite slučaj kada imate nekoliko kartica otvorenih u prozoru preglednika. Zatim, svaka kartica radi istovremeno i može se nazvati a Nit . Pod pretpostavkom da koristimo Microsoft Excel , jedna nit će upravljati oblikovanje teksta , a jedna nit će upravljati unosom . Stoga C-ova značajka višenitnosti olakšava izvršavanje više zadataka odjednom. Stvaranje niti je znatno brže. Prijenos konteksta preko niti odvija se brže. Dodatno, komunikacija između niti se može ostvariti brže, a prekidanje niti je jednostavno.

Kako napisati C programe za višenitnost?

Iako višenitne aplikacije nisu ugrađene u jezik C, moguće je ovisno o operativnom sustavu. The niti.h standardna biblioteka koristi se za implementaciju ideje višenitnosti C . Međutim, trenutno ne postoji kompilator koji to može učiniti. Moramo koristiti implementacije specifične za platformu, kao što je 'POSIX' biblioteka niti, korištenjem datoteke zaglavlja pnit.h , ako želimo koristiti višenitnost u C-u. 'Pthreads' je drugo ime za ovo. A POSIX niti se mogu kreirati na sljedeće načine:

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

U ovom slučaju, Pthread_create stvara novu nit kako bi nit bila izvršna. Omogućuje vam implementaciju višenitnosti u C koliko god puta želite u svom kodu. Ovdje su navedeni parametri i njihovi opisi od ranije.

nit:

To je singularna identifikacija da je podproces vraća .

attr:

Kada želimo postaviti atribute niti, koristimo ovo neproziran atribut .

početak_rutine:

Kada početak_rutine generira se, nit će pokrenuti rutinu.

arg:

Parametar koji početak_rutine prima. NULL koristit će se ako nema argumenata.

Određeni primjeri C višenitnosti

Evo nekoliko primjera problema s višenitnošću u C-u.

1. Pitanje čitatelja i pisca

Čest problem operativnog sustava sa sinkronizacijom procesa je problem čitača/pisca . Pretpostavimo da imamo bazu podataka koja Čitatelji i Književnici , dvije različite kategorije korisnika, mogu pristupiti. Čitatelji su jedini koji mogu čitati baze podataka, dok Književnici su jedini koji mogu čitati bazu podataka i također je ažurirati. Iskoristimo IRCTC kao jednostavan primjer. Ako želimo provjeriti status određenog broj vlaka , jednostavno unesite broj vlaka u sustav kako biste vidjeli relevantne informacije o vlaku. Ovdje su prikazane samo informacije koje su prisutne na web stranici. Operator čitanja je ovo. Međutim, ako želimo rezervirati kartu, moramo ispuniti obrazac za rezervaciju karte s detaljima kao što su naše ime, dob i tako dalje. Dakle, ovdje ćemo izvesti operaciju pisanja. Napravit će se neke prilagodbe IRCTC baza podataka .

Problem je u tome što nekoliko ljudi istovremeno pokušava pristupiti IRCTC baza podataka . Oni bi mogli biti a pisac ili a čitač . Problem nastaje ako čitatelj već koristi bazu podataka, a pisac joj istovremeno pristupa radi rada na istim podacima. Drugi problem nastaje kada pisac koristi bazu podataka, a čitatelj pristupa istim informacijama kao i baza podataka. Treće, postoji poteškoća kada jedan pisac ažurira bazu podataka dok drugi pokušava ažurirati podatke u istoj bazi podataka. Četvrti scenarij događa se kada dva čitatelja pokušaju dohvatiti isti materijal. Sva ova pitanja nastaju ako čitatelj i pisac koriste iste podatke baze podataka.

Semafor je metoda koja se koristi za rješavanje ovog problema. Pogledajmo ilustraciju kako koristiti ovaj problem.

Proces čitanja:

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

Obrazloženje:

U ovom kodu imamo dijeljene podatke varijable i broj čitatelja rc . The prema stanju varijabla se koristi za ograničavanje pristupa za spisateljski proces , i mutex koristi se za jamčenje međusobnog isključivanja za pristup dijeljenim podacima.

Čitateljski proces predstavlja reader() funkcija . The broj čitatelja (rc) se povećava prije postizanja mutex zaključavanje . Koristi se pthread_cond_wait() čekati na prema stanju varijabla ako je prvi čitatelj (rc == 1) . Kao rezultat toga, piscima će biti onemogućeno pisanje dok svi čitači ne završe.

Proces čitanja provjerava je li to bio posljednji čitatelj (rc == 0) a spušta čitač brojati (rc--) nakon čitanja zajedničkih podataka. ako je bilo, pthread_cond_signal() signalizira prema stanju varijabla za nastavak procesa pisanja na čekanju.

Koristiti pthread_create() i funkcije pthread_join(). , mi novi i pridružiti više čitateljskih niti u glavna funkcija . Pojedinačni ID dodjeljuje se svakoj niti čitača u svrhu identifikacije.

Proces pisca:

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

U gornjem primjeru, isto kao i čitateljski proces , provodi se operacija poznata kao operacija čekanja 'wrt' kada korisnik želi pristupiti podacima ili objektu. Nakon toga novi korisnik neće moći pristupiti objektu. A nakon što korisnik završi s pisanjem, izvršava se druga operacija signala wrt .

2. problem zaključavanja i otključavanja:

Ideja a mutex koristi se u višenitnosti u C-u kako bi se zajamčilo da neće biti stanje utrke između niti . Kada više niti počne obrađivati ​​iste podatke odjednom, ta je okolnost poznata kao utrkivanje . Međutim, ako te okolnosti postoje, moramo. Koristimo se zaključavanje mutexa() i unlock() funkcije osigurati određeni dio koda za određenu nit. Tako da druga nit ne može početi izvoditi istu operaciju. The 'kritična sekcija/regija' je naziv dat ovom zaštićenom području koda. Prije korištenja zajedničkih resursa postavljamo puno na određenom području, a nakon što ih završimo s korištenjem, ponovno ih otključavamo.

Ispitajmo rad mutexa za zaključavanje i otključavanje u višenitnosti u C-u:

Primjer:

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

Obrazloženje:

java povratna naredba

U ovom gornjem primjeru objašnjavamo kako mi zaključati i otključati određeno područje koda koje nas štiti od trkaće situacije. 'pthread_mutex_t' koristi se kao inicijalizator u gornjem primjeru. 'pthread_mutex_lock' je tada napisano prije početka šifre koju želimo zaključati. Kodiranje koje želimo zaključati je nakon toga gotovo. Nakon toga se zaključavanje šifre prekida korištenjem 'pthread_mutex_unlock' ; ubuduće nijedan kôd neće biti u načinu zaključavanja.

Problem filozofa blagovanja:

Jedan od klasičnih problema sa sinkronizacijom je dining philosopher problem . Potrebna je jednostavna dodjela resursa za nekoliko procesa, ali ne bi trebala rezultirati a pat ili glad . The dining philosopher problem može se promatrati kao izravan prikaz niza procesa, od kojih svaki zahtijeva resurse. Budući da svaki od ovih procesa zahtijeva raspodjelu resursa, potrebno je te resurse rasporediti po svim procesima tako da niti jedan proces nikada ne zapne ili prestane raditi.

Pretpostavimo da pet filozofa sjedi u a stol u obliku kruga . U jednom trenutku jedu, au drugom razmišljaju o nečemu. Oko okruglog stola filozofi su ravnomjerno raspoređeni na stolicama. Uz to, na sredini stola nalazi se zdjela riže i pet štapića za svakog filozofa. Kada filozof osjeća da ne može komunicirati sa svojim kolegama koji sjede u blizini.

Filozof povremeno uzme dva štapića kad ogladni. Ona bira dva štapića od svojih susjeda - jedan na njoj lijevo a jedan na njoj pravo - koji su nadohvat ruke. Ali filozof nikada ne bi trebao uzeti više od jednog štapića odjednom. Očito neće moći podići štapić koji susjed koristi.

Primjer:

Iskoristimo primjer da pokažemo kako je to implementirano u C-u.

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

Obrazloženje:

Štapići za jelo može se prikazati semaforom. Budući da postoje štapići za jelo na stolu i niti jedan filozof nije odabrao jedan, sve komponente štapića prvo se inicijaliziraju na 1 . Sada to štapić[i] je izabran kao prvi štapić za jelo. štapić[i] i štapić za jelo[(i+1)%5] podliježu prvoj operaciji čekanja. ove operacija čekanja štapićima ukazuje da ih je filozof pokupio. Proces jedenja počinje kada filozof odabere svoje štapić za jelo . Operacija signala sada se provodi na štapići [i] i [(i+1)%5] nakon što je filozof završio s jelom. Filozof se tada vraća u san.

pretvorba datuma u niz

Kako bi se utvrdilo je li podnit se pridružio glavnoj niti ili ne, koristili smo funkcija pthread_join . Slično tome, provjerili smo je li mutex zaključavanje je inicijalizirano pomoću pthread_mutex_init metoda.

Za inicijalizaciju i provjeru je li nova nit stvorena ili ne, upotrijebili smo pthread_create funkcija . Slično ovome, uništili smo mutex zaključavanje koristiti pthread_mutex_destroy funkcija.

Problem proizvođač-potrošač:

Čest problem sa sinkronizacijom višenitnog procesa je problem proizvođač-potrošač . U njemu su prisutna dva procesa: prvi je proizvođački proces , a drugi je potrošački proces . Nadalje, pretpostavlja se da se obje operacije odvijaju istodobno i paralelno. Osim toga, oni su proces suradnje, što implicira da dijele nešto jedni s drugima. Važno je da kada je međuspremnik puna , proizvođač ne može dodati podatke. Kada je međuspremnik prazan, potrošač ne može izdvojiti podatke iz međuspremnika jer je zajednička veličina međuspremnika između proizvođača i potrošača fiksni . Problem je postavljen na ovaj način. Stoga, da bismo implementirali problem proizvođač-potrošač i riješili ga, koristit ćemo ideju paralelnog programiranja.

Primjer:

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

Izlaz:

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

Obrazloženje:

Obavljamo dva zadatka. Funkcije potrošač() i proizvođač() ukazuju na status i rad potrošač i proizvođač . The producent() metoda će stvoriti mutex zaključavanje i utvrditi je li međuspremnik puna kad se zove. Kada je međuspremnik pun, ništa se neće proizvoditi. Ako ne, hoće stvoriti , a zatim, nakon proizvodnja , stavit će se u stanje mirovanja kako bi otključao mutex zaključavanje . Poput proizvođač , potrošač prvo stvara mutex zaključavanje , provjerava pufer , troši proizvod , a zatim otključava prije povratka na spavanje.

A brojač (x) koristit će se tijekom proizvodnje i nastavit će rasti sve dok proizvođač ne proizvede predmet. Međutim, potrošač će manje toga proizvoditi stavka (x) .

Zaključak:

Ideja korištenja dva ili više niti za izvođenje programa poznato je kao višenitnosti u programskom jeziku C. Višenitnost omogućuje istovremeno izvršavanje nekoliko zadataka. Najjednostavnija izvršna komponenta programa je a nit . Proces je ideja da se zadatak može dovršiti razbijanjem na nekoliko manjih podprocesi .

Datoteka zaglavlja pnit.h potreban je za implementaciju višenitnosti u C-u budući da se ne može učiniti izravno.