logo

MULTIPLEACIÓ EN C

Introducció:

En C, el terme 'multithreading' descriu l'ús de nombrosos fils simultàniament. Cada fil fa a tasca diferent . A causa de la naturalesa concurrent del multithreading, es poden dur a terme moltes tasques alhora. A més, multithreading redueix la Ús de recursos de la CPU . Hi ha dues categories de multitasca: basat en processos i basat en fils . Quan qualsevol cosa es descriu com a multiprocés, significa que almenys dos o potser més fils s'estan executant en el mateix procés alhora. Primer hem d'entendre què són un fil i un procés per entendre el multithreading en C. Vegem aquests temes per entendre-ho millor.

diferència entre dues cadenes python

Què són els processos i els fils?

A fil és el edifici fonamental bloc de l'execució de qualsevol procés. Un programa està format per diversos processos, i cada procés està format per fils, que són unitats molt més bàsiques. Per tant, el fil pot considerar-se el bloc de construcció fonamental d'un procés o la unitat més senzilla que determina conjuntament la utilització de la CPU.

Els elements següents s'inclouen en un fil:

ID del fil:

És un especial ID del fil que es genera en el moment de la formació del fil i es manté durant la durada del fil específic.

Comptador de programes:

És un valor que el càrregues de maquinari .

Un conjunt registrat:

És una col·lecció de registres comuns .

Una pila:

És una resta d'això fil específic .

A més, si dos fils funcionen simultàniament en el mateix procés, es comparteixen codi , seccions de dades , i altres recursos del sistema operatiu com ara fitxer s'obre i senyals . Un procés pesat, un tipus de procés convencional, pot controlar un fil. Tanmateix, un control multifils té la capacitat d'obrir i dur a terme múltiples tasques simultàniament. El sistema esdevé considerablement més efectiu com a resultat de l'ús de fils, per això són útils.

La distinció entre solter i multithreading en C s'explica. En primer lloc, és a procés d'un sol fil . Com a resultat, tot el bloc, inclòs el codi, dades, etc.-es considera com un procés, i aquest procés només té un fil. Significa que aquesta tècnica completarà només una tasca a la vegada. Però hi ha un procés multithreading que s'oposa a això. Hi ha activitats com codi, pila, dades , i Fitxers també, però s'estan realitzant mitjançant diversos fils, cadascun dels quals té la seva pròpia pila i registres. Atès que en aquesta situació es poden realitzar nombroses tasques alhora, el procés es coneix com a procés multithreading .

El fil es presenta en dues varietats:

Fil a nivell d'usuari:

És a nivell d'usuari, com el seu nom implica. El nucli no té accés a les seves dades.

Fil a nivell del nucli

El tipus de fil fa referència a la relació del fil amb el nucli i el sistema operatiu del sistema.

procés- La sèrie de passos realitzats per dur a terme un programa es pot denominar procés . Un programa no s'executa immediatament quan s'executa. Es divideix en uns quants passos bàsics que es porten a terme seqüencialment de manera organitzada per conduir a l'execució d'un procés eventualment.

Un procés que s'ha desglossat en passos més petits s'anomena a 'clon o procés fill', mentre que el procés original es coneix com a procés 'parent' . A la memòria, cada procés utilitza una certa quantitat d'espai que no es comparteix amb cap altre procés.

Un procediment passa per algunes etapes abans de l'execució.

imprimir matriu en java

NOU-

En aquesta situació, un nou procés és generat .

PREPARAT-

Quan es prepara un procés i s'espera que s'assigni un processador, es troba en aquest estat.

CÓRRER-

Quan el procés està actiu, és l'estat.

ESPERANT-

Quan un procés està en aquest estat, hi ha alguna cosa esperant succeir.

TERMINAT-

c++ int a cadena

És l'estat en què s'està duent a terme el tràmit.

Per què C és multiprocés?

Multithreading a la idea C es pot aprofitar mitjançant el paral·lelisme per millorar an funcionalitat de l'aplicació . Considereu el cas en què teniu diverses pestanyes obertes en una finestra del navegador. Aleshores, cada pestanya funciona simultàniament i es pot anomenar a Fil . Suposant que fem servir Microsoft Excel , un fil gestionarà format del text , i un fil ho farà gestionar l'entrada . Per tant, la funció multithreading de C facilita la realització de diverses tasques alhora. La creació d'un fil és considerablement més ràpida. La transferència de context entre fils es fa més ràpidament. A més, la comunicació entre fils es pot fer més ràpidament i la terminació del fil és senzilla.

Com escriure programes C per a multiprocés?

Tot i que les aplicacions multithreading no estan integrades en el llenguatge C, és possible en funció del sistema operatiu. El threads.h biblioteca estàndard s'utilitza per implementar la idea multithreading a C . Tanmateix, actualment no hi ha cap compilador que pugui fer-ho. Hem d'utilitzar implementacions específiques de la plataforma, com ara 'POSIX' biblioteca de fils, utilitzant el fitxer de capçalera pthread.h , si volem utilitzar multithreading a C. 'Pthreads' és un altre nom per a això. A POSIX El fil es pot crear de les maneres següents:

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

En aquest cas, Pthread_create crea un fil nou per fer-lo executable. Us permet implementar multithreading en C tantes vegades com vulgueu al vostre codi. Aquí s'enumeren els paràmetres i les seves descripcions anteriors.

fil:

És un identificació singular que la retorns de subprocés .

attr:

Quan volem establir atributs de fil, fem servir això atribut opac .

rutina_inici:

Quan iniciar_rutina es genera, el fil executarà una rutina.

arg:

El paràmetre que el iniciar_rutina rep. NUL s'utilitzarà si no es donen arguments.

Alguns exemples de multithreading C

Aquests són alguns exemples de problemes de multiprocés a C.

1. El tema lector-escriptor

Un problema comú del sistema operatiu amb la sincronització de processos és el problema lector/escriptor . Suposem que tenim una base de dades que Lectors i Escriptors , dues categories d'usuaris diferents, poden accedir. Lectors són els únics que poden llegir la base de dades, mentre que Escriptors són els únics que poden llegir la base de dades i actualitzar-la també. Fem servir IRCTC com a simple exemple. Si volem comprovar l'estat d'un determinat número de tren , només cal que introduïu el número del tren al sistema per veure la informació del tren pertinent. Aquí només es mostra la informació que hi ha al lloc web. L'operador de lectura és aquest. Tanmateix, si volem reservar una entrada, haurem d'omplir el formulari de reserva d'entrades amb dades com el nostre nom, edat, etc. Per tant, farem una operació d'escriptura aquí. Es faran alguns ajustaments al Base de dades IRCTC .

El problema és que diverses persones intenten accedir simultàniament Base de dades IRCTC . Poden ser a escriptor o a lector . El problema sorgeix si un lector ja està utilitzant la base de dades i un escriptor hi accedeix simultàniament per treballar amb les mateixes dades. Un altre problema sorgeix quan un escriptor utilitza una base de dades i un lector accedeix a la mateixa informació que la base de dades. En tercer lloc, hi ha una dificultat quan un escriptor actualitza la base de dades mentre un altre intenta actualitzar les dades de la mateixa base de dades. El quart escenari es produeix quan dos lectors intenten recuperar el mateix material. Tots aquests problemes sorgeixen si el lector i l'escriptor utilitzen les mateixes dades de base de dades.

El semàfor és un mètode que s'utilitza per resoldre aquest problema. Vegem una il·lustració de com utilitzar aquest problema.

Procés del lector:

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

Explicació:

En aquest codi, tenim les dades de la variable compartida i el recompte de lectors rc . El wrt condició La variable s'utilitza per limitar l'accés per a procés d'escriptor , i la mutex s'utilitza per garantir l'exclusió mútua per accedir a les dades compartides.

El procés lector està representat per la funció reader(). . El recompte de lectors (rc) s'incrementa abans d'assolir el bloqueig mutex . S'utilitza pthread_cond_wait() per esperar el wrt condició variable si és la primer lector (rc == 1) . Com a resultat, els escriptors no podran escriure fins que tots els lectors hagin acabat.

El procés del lector comprova si va ser el últim lector (rc == 0) i baixa el lector comptar (rc--) després de llegir les dades compartides. Si fos, pthread_cond_signal() senyala el wrt condició variable per permetre que els processos d'escriptura en espera continuïn.

Utilitzant el pthread_create() i funcions pthread_join(). , nosaltres nou i uneix-te múltiples fils de lectors al funció main(). . S'assigna un identificador individual a cada fil de lector amb finalitats d'identificació.

Procés de l'escriptor:

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

A l'exemple anterior, igual que el procés lector , es realitza una operació coneguda com a operació d'espera 'wrt' quan un usuari vol accedir a les dades o objecte. Després d'això, el nou usuari no podrà accedir a l'objecte. I un cop l'usuari ha acabat d'escriure, es realitza una altra operació de senyal wrt .

2. problema de bloqueig i desbloqueig:

La idea d'a mutex s'utilitza en multithreading en C per garantir que no hi haurà a condició de carrera entre fils . Quan diversos fils comencen a processar les mateixes dades alhora, aquesta circumstància es coneix com carreres . Tanmateix, si es donen aquestes circumstàncies, ho hem de fer. Fem servir el bloqueig de mutex () i funcions unlock(). per assegurar una secció concreta de codi per a un fil específic. De manera que, un altre fil no pot començar a realitzar la mateixa operació. El 'secció/regió crítica' és el nom donat a aquesta àrea de codi protegit. Abans d'utilitzar els recursos compartits, ens instal·lem molt en una àrea determinada i, un cop els acabem d'utilitzar, els desbloquegem una vegada més.

Examinem el funcionament del mutex per bloquejar i desbloquejar en multithreading a C:

Exemple:

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

Explicació:

algorisme de kruskals

En aquest exemple anterior, expliquem com pany i descobrir una determinada regió de codi que ens protegeix de la situació de les carreres. 'pthread_mutex_t' s'utilitza com a inicialitzador a l'exemple anterior. 'pthread_mutex_lock' és aleshores escrit abans de l'inici del codi que volem bloquejar. La codificació que volem bloquejar s'ha acabat després. Després d'això, el bloqueig del codi s'acaba utilitzant 'pthread_mutex_unlock' ; en endavant, cap codi estarà en mode de bloqueig.

bucle bash while

El problema del filòsof de menjador:

Un dels problemes clàssics de la sincronització és el tema del filòsof de menjador . Es requereix una assignació simple de recursos per a diversos processos, però no hauria de donar lloc a un estancament o fam . El problema del filòsof de menjador es pot veure com una representació directa d'una sèrie de processos, cadascun dels quals exigeix ​​recursos. Com que cadascun d'aquests processos requereix una assignació de recursos, és necessari distribuir aquests recursos entre tots els processos perquè mai cap procés s'encalli o deixi de funcionar.

Suposem que hi ha cinc filòsofs asseguts a a taula en forma de cercle . Mengen en un moment i reflexionen sobre alguna cosa en un altre. Al voltant de la taula rodona, els filòsofs estan distribuïts uniformement sobre les cadires. A més, hi ha un bol d'arròs i cinc escuradents per a cada filòsof al mig de la taula. Quan el filòsof sent que no pot interactuar amb els seus col·legues asseguts a prop.

De tant en tant, una filòsofa agafa dos escuradents quan té gana. Tria dos escuradents dels seus veïns, un d'ella esquerra i una sobre ella dret -que són de fàcil accés. Però el filòsof mai hauria d'agafar més d'un escuradents alhora. Evidentment, no podrà agafar l'escuradents que fa servir el veí.

Exemple:

Utilitzem un exemple per demostrar com s'implementa això a 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;>

Explicació:

Escuradents es pot representar amb un semàfor. Des que n'hi ha escuradents sobre la taula i cap filòsof n'ha triat cap, tots els components dels escuradents s'inicialitzen primer a 1 . Ara que escuradents[i] ha estat escollit com el primer escuradents. escuradents[i] i escuradents[(i+1)%5] estan subjectes a la primera operació d'espera. Aquests operació d'espera dels escuradents indica que el filòsof els ha recollit. El procés de menjar comença un cop el filòsof selecciona el seu escuradents . L'operació del senyal es porta a terme ara al escuradents [i] i [(i+1)%5] un cop el filòsof ha acabat de menjar. Aleshores, el filòsof es torna a dormir.

Per determinar si el subfil s'ha unit al fil principal o no, hem utilitzat el funció pthread_join . De la mateixa manera, hem comprovat si el mutex el bloqueig s'ha inicialitzat amb el pthread_mutex_init mètode.

Per inicialitzar i verificar si el fil nou es va crear o no, hem utilitzat el funció pthread_create . De manera semblant a això, vam destruir el bloqueig mutex utilitzant el pthread_mutex_destroy funció.

El problema productor-consumidor:

Un problema comú amb la sincronització de processos multithreading és el problema productor-consumidor . Hi ha dos processos presents: el primer és el procés del productor , i el segon és el procés del consumidor . A més, s'assumeix que ambdues operacions s'estan produint simultàniament en paral·lel. A més, són un procés cooperatiu, la qual cosa implica que estan compartint alguna cosa entre ells. És important que quan estigui el buffer ple , el productor no pot afegir dades. Quan el buffer està buit, el consumidor no pot extreure dades del buffer perquè la mida comuna del buffer entre el productor i el consumidor és fixat . La qüestió s'exposa d'aquesta manera. Per tant, per implementar el problema productor-consumidor i resoldre'l, utilitzarem la idea de programació paral·lela.

Exemple:

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

Sortida:

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

Explicació:

Realitzem dues tasques. Les funcions consumidor () i productor() indicar l'estat i el funcionament del consumidor i productor . El mètode productor(). crearà el bloqueig mutex i determinar si el buffer és ple quan es diu. Quan el buffer estigui ple, no es produirà res. Si no, ho farà crear , i després, després del producció , es posarà a dormir per desbloquejar el bloqueig mutex . Com el productor , el consumidor crea primer el bloqueig mutex , comprova el tampó , consumeix el producte , i després allibera el bloqueig abans de tornar a dormir.

A comptador (x) s'utilitzarà durant la fabricació i seguirà creixent fins que el fabricant produeixi l'article. No obstant això, el consumidor farà menys del mateix fabricat element (x) .

Conclusió:

La idea d'utilitzar dos o més fils executar un programa es coneix com multithreading en el llenguatge de programació C. Multithreading permet l'execució simultània de diverses tasques. El component executable més senzill d'un programa és a fil . El procés és la idea que una tasca es pot completar dividint-la en diverses més petites subprocessos .

El fitxer de capçalera pthread.h es requereix per implementar multithreading en C ja que no es pot fer directament.