logo

تعدد الخيوط في C

مقدمة:

في ج، المصطلح 'تعدد مؤشرات الترابط' يصف استخدام العديد الخيوط بشكل متزامن. كل موضوع يفعل مهمة مختلفة . نظرًا للطبيعة المتزامنة لتعدد العمليات، يمكن تنفيذ العديد من المهام في وقت واحد. بالإضافة إلى ذلك، تعدد المواضيع يقلل من استخدام موارد وحدة المعالجة المركزية . هناك فئتان من المهام المتعددة: على أساس العملية و على أساس الموضوع . عندما يتم وصف أي شيء على أنه تعدد مؤشرات الترابط، فهذا يعني أن خيطين أو ربما أكثر يعملان في نفس العملية في وقت واحد. يجب علينا أولاً أن نفهم ما هو الخيط والعملية حتى نتمكن من فهم تعدد مؤشرات الترابط في لغة C. دعونا نلقي نظرة على هذه المواضيع للحصول على فهم أفضل.

أنواع البيانات البدائية في جافا

ما هي العمليات والخيوط؟

أ خيط هل بناء أساسي حاجز من تنفيذ أي عملية. يتكون البرنامج من عدة عمليات، وكل عملية تتكون من خيوط، وهي وحدات أساسية أكثر بكثير. لذلك، يمكن اعتبار مؤشر الترابط لبنة البناء الأساسية للعملية أو الوحدة الأبسط التي تحدد بشكل مشترك استخدام وحدة المعالجة المركزية.

يتم تضمين العناصر التالية في الموضوع:

معرف الموضوع:

إنها خاصة معرف الخيط التي يتم إنشاؤها في وقت تكوين الخيط ويتم الاحتفاظ بها طوال مدة الخيط المحددة.

عداد البرنامج :

وهي القيمة التي أحمال الأجهزة .

مجموعة مسجلة:

وهي عبارة عن مجموعة من السجلات المشتركة .

كومة:

إنها بقايا من ذلك موضوع معين .

بالإضافة إلى ذلك، إذا كان هناك خيطان يعملان في نفس الوقت في نفس العملية، فإنهما يتشاركان شفرة , أقسام البيانات وموارد نظام التشغيل الأخرى مثل file يفتح و إشارات . عملية ثقيلة الوزن، وهي نوع من العمليات التقليدية، يمكنها التحكم في خيط واحد. ومع ذلك، فإن خيوط التحكم المتعددة لديها القدرة على فتح وتنفيذ مهام متعددة في وقت واحد. يصبح النظام أكثر فعالية إلى حد كبير نتيجة لاستخدام الخيوط، وهذا هو السبب في أنها مفيدة.

التمييز بين أعزب و تعدد المواضيع في C تم شرحه. بادئ ذي بدء، هو أ عملية ذات خيط واحد . ونتيجة لذلك، فإن الكتلة بأكملها - بما في ذلك البيانات, إلخ- تعتبر عملية واحدة، وهذه العملية لها خيط واحد فقط. وهذا يعني أن هذه التقنية ستكمل مهمة واحدة فقط في كل مرة. ولكن هناك عملية تعدد الخيوط الذي يقف ضد هذا. هناك أنشطة مثل الكود، المكدس، البيانات ، و ملفات أيضًا، ولكن يتم تنفيذها بواسطة عدة سلاسل رسائل، لكل منها مكدس وسجلات خاصة به. نظرًا لأنه يمكن إكمال العديد من المهام مرة واحدة في هذه الحالة، تُعرف العملية باسم أ عملية تعدد الخيوط .

الخيط يأتي في نوعين:

الموضوع على مستوى المستخدم:

إنه على مستوى المستخدم، كما يوحي الاسم. لا يتم منح النواة حق الوصول إلى بياناتها.

الموضوع على مستوى النواة

يشير نوع الخيط إلى علاقة الخيط بالنواة ونظام التشغيل الخاص بالنظام.

عملية- يمكن الإشارة إلى سلسلة الخطوات المتخذة لتنفيذ البرنامج باسم عملية . لا يتم تنفيذ البرنامج على الفور عند تشغيله. يتم تقسيمها إلى بضع خطوات أساسية يتم تنفيذها بشكل تسلسلي بطريقة منظمة لتؤدي إلى تنفيذ العملية في النهاية.

يشار إلى العملية التي تم تقسيمها إلى خطوات أصغر باسم أ 'عملية الاستنساخ أو الطفل'، بينما يشار إلى العملية الأصلية باسم عملية 'الوالدين'. . في الذاكرة، تستخدم كل عملية مقدارًا معينًا من المساحة التي لا تتم مشاركتها مع أي عمليات أخرى.

يمر الإجراء ببعض المراحل قبل التنفيذ.

جديد-

في هذه الحالة، هناك عملية جديدة ولدت .

مستعد-

خوارزمية البحث الثنائي

عندما يتم إعداد عملية ما وانتظار تعيين المعالج، تكون في هذه الحالة.

جري-

عندما تكون العملية نشطة، فهي الدولة.

منتظر-

عندما تكون العملية في هذه الحالة، يكون هناك شيء ما منتظر يحدث.

تم الإنهاء-

هي الحالة التي يتم فيها تنفيذ الإجراء.

لماذا لغة C متعددة الخيوط؟

تعدد الخيوط في فكرة C يمكن الاستفادة منها من خلال التوازي لتعزيز وظيفة التطبيق . ضع في اعتبارك الحالة التي يكون لديك فيها عدة علامات تبويب مفتوحة في نافذة المتصفح. بعد ذلك، تعمل كل علامة تبويب بشكل متزامن وقد يشار إليها باسم a خيط . لنفترض أننا نستخدم مايكروسوفت اكسل ، سيتم إدارة موضوع واحد تنسيق النص ، وسوف موضوع واحد التعامل مع الإدخال . ولذلك، فإن ميزة تعدد مؤشرات الترابط في لغة C تجعل من السهل تنفيذ مهام متعددة في وقت واحد. يعد إنشاء الخيط أسرع بكثير. يحدث نقل السياق عبر سلاسل الرسائل بسرعة أكبر. بالإضافة إلى ذلك، يمكن إجراء الاتصال بين سلاسل العمليات بشكل أسرع، كما أن إنهاء سلاسل المحادثات يكون بسيطًا.

كيفية كتابة برامج C لتعدد مؤشرات الترابط؟

على الرغم من أن تطبيقات مؤشرات الترابط المتعددة ليست مدمجة في لغة C، إلا أنها ممكنة اعتمادًا على نظام التشغيل. ال مكتبة Threads.h القياسية يستخدم لتنفيذ فكرة تعدد مؤشرات الترابط في ج . ومع ذلك، لا يوجد حاليًا أي مترجم يمكنه القيام بذلك. يجب أن نستخدم تطبيقات خاصة بالمنصة، مثل 'بوسيكس' مكتبة المواضيع، وذلك باستخدام ملف الرأس pthread.h ، إذا أردنا استخدام تعدد مؤشرات الترابط في لغة C. 'الخيوط' هو اسم آخر لهذا. أ بوسيكس يمكن إنشاء الخيط بالطرق التالية:

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

في هذه الحالة، Pthread_create يقوم بإنشاء موضوع جديد لجعل الموضوع قابلاً للتنفيذ. يسمح لك بتنفيذ تعدد مؤشرات الترابط في لغة C عدة مرات كما تريد في التعليمات البرمجية الخاصة بك. يتم سرد المعلمات وأوصافها من قبل هنا.

خيط:

إنها تحديد المفرد أن إرجاع العملية الفرعية .

وظيفة مركز حقوق الإنسان بيثون

أتر:

عندما نريد تعيين سمات الموضوع، نستخدم هذا سمة مبهمة .

روتين_البدء:

متى start_routine يتم إنشاء الخيط، سيتم تشغيل روتين.

الارجنتين:

المعلمة التي start_routine يستقبل. باطل سيتم استخدامها إذا لم يتم تقديم أي وسائط.

بعض أمثلة تعدد مؤشرات الترابط C

فيما يلي بعض الأمثلة على مشكلات تعدد العمليات في لغة C.

1. قضية القارئ والكاتب

إحدى مشكلات نظام التشغيل الشائعة المتعلقة بمزامنة العمليات هي مشكلة القارئ/الكاتب . لنفترض أن لدينا قاعدة بيانات ذلك القراء و الكتاب ، يمكن لفئتين مختلفتين من المستخدمين الوصول إليها. القراء هم الوحيدون الذين يستطيعون يقرأ قاعدة البيانات، في حين الكتاب هم الوحيدون الذين يمكنهم قراءة قاعدة البيانات وتحديثها أيضًا. لنستخدم IRCTC كمثال بسيط. إذا أردنا التحقق من حالة معينة رقم القطار ، ما عليك سوى إدخال رقم القطار في النظام لعرض معلومات القطار ذات الصلة. يتم عرض المعلومات الموجودة على الموقع فقط هنا. عامل القراءة هو هذا. ومع ذلك، إذا أردنا حجز تذكرة، فيجب علينا ملء نموذج حجز التذكرة بتفاصيل مثل الاسم والعمر وما إلى ذلك. لذلك، سنقوم بإجراء عملية الكتابة هنا. سيتم إجراء بعض التعديلات على قاعدة بيانات IRCTC .

تكمن المشكلة في أن العديد من الأشخاص يحاولون الوصول إلى الملف في نفس الوقت قاعدة بيانات IRCTC . قد يكونون أ كاتب أو أ قارئ . تنشأ المشكلة إذا كان القارئ يستخدم قاعدة البيانات بالفعل ويصل إليها الكاتب في وقت واحد للعمل على نفس البيانات. تنشأ مشكلة أخرى عندما يستخدم الكاتب قاعدة بيانات، ويصل القارئ إلى نفس المعلومات مثل قاعدة البيانات. ثالثًا، هناك صعوبة عندما يقوم أحد الكاتبين بتحديث قاعدة البيانات بينما يحاول كاتب آخر تحديث البيانات الموجودة على نفس قاعدة البيانات. السيناريو الرابع يحدث عندما يحاول قارئان استرجاع نفس المادة. تنشأ كل هذه المشكلات إذا استخدم القارئ والكاتب نفس بيانات قاعدة البيانات.

Semaphore هي الطريقة المستخدمة لحل هذه المشكلة. دعونا نلقي نظرة على الرسم التوضيحي لكيفية استخدام هذه المشكلة.

عملية القارئ:

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

توضيح:

في هذا الكود، لدينا بيانات المتغير المشترك و عدد القراء RC . ال حالة مكتوبة يتم استخدام المتغير لتقييد الوصول إلى عملية الكاتب ، و ال كائن المزامنة يستخدم لضمان الاستبعاد المتبادل للوصول إلى البيانات المشتركة.

يتم تمثيل عملية القارئ بواسطة وظيفة القارئ (). . ال عدد القراء (RC) يتم زيادتها قبل الوصول إلى قفل كائن المزامنة . يستخدم pthread_cond_wait() للانتظار على حالة مكتوبة المتغير إذا كان القارئ الأول (rc == 1) . ونتيجة لذلك، سيتم منع الكتاب من الكتابة حتى الانتهاء من جميع القراء.

تتحقق عملية القارئ مما إذا كان الملف القارئ الأخير (rc == 0) ويخفض القارئ العد (RC--) بعد قراءة البيانات المشتركة. إذا كانت، pthread_cond_signal() يشير إلى حالة مكتوبة متغير للسماح باستمرار عمليات الكاتب المنتظرة.

باستخدام pthread_create() و وظائف pthread_join() ، نحن جديد و ينضم مؤشرات ترابط متعددة للقارئ في الوظيفة الأساسية . يتم تعيين معرف فردي لكل موضوع قارئ لأغراض التعريف.

عملية الكاتب:

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

في المثال أعلاه، نفس عملية القارئ ، يتم تنفيذ عملية تعرف باسم عملية الانتظار 'كتاب' عندما يرغب المستخدم في الوصول إلى البيانات أو الكائن. وبعد ذلك، لن يتمكن المستخدم الجديد من الوصول إلى الكائن. وبمجرد انتهاء المستخدم من الكتابة، يتم تنفيذ عملية إشارة أخرى wrt .

2. مشكلة القفل والفتح:

فكرة أ كائن المزامنة يتم استخدامه في مؤشرات الترابط المتعددة في لغة C لضمان عدم وجود ملف حالة السباق بين ال الخيوط . عندما تبدأ عدة سلاسل عمليات في معالجة نفس البيانات مرة واحدة، يُعرف هذا الظرف باسم سباق . ومع ذلك، إذا كانت هذه الظروف موجودة، فيجب علينا ذلك. نحن نستخدم ال قفل كائن المزامنة () و وظائف فتح (). لتأمين قسم معين من التعليمات البرمجية لموضوع معين. بحيث لا يمكن لخيط آخر أن يبدأ في تنفيذ نفس العملية. ال 'القسم/المنطقة الحرجة' هو الاسم المعطى لمنطقة التعليمات البرمجية المحمية هذه. قبل استخدام الموارد المشتركة، قمنا بإعداد الكثير في منطقة معينة، وبمجرد الانتهاء من استخدامها، نقوم بفتحها مرة أخرى.

دعونا نفحص تشغيل كائن المزامنة (mutex) للقفل والفتح في مؤشرات الترابط المتعددة في لغة C:

مثال:

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

توضيح:

android.process.acore يستمر في التوقف

في هذا المثال أعلاه، نوضح كيف أننا قفل و الغاء القفل منطقة معينة من التعليمات البرمجية التي تحمينا من حالة السباق. 'pthread_mutex_t' يستخدم ك مُهيئ في المثال أعلاه. 'pthread_mutex_lock' هو ذلك الحين مكتوب قبل بداية الكود الذي نريد قفله. يتم الانتهاء من الترميز الذي نرغب في قفله بعد ذلك. بعد ذلك، يتم إنهاء قفل الرمز باستخدام 'pthread_mutex_unlock' ; من الآن فصاعدًا، لن يكون هناك أي رمز في وضع القفل.

مشكلة فيلسوف تناول الطعام:

إحدى المشكلات الكلاسيكية المتعلقة بالمزامنة هي قضية تناول الطعام الفيلسوف . مطلوب تخصيص الموارد البسيطة لعدة عمليات ولكن لا ينبغي أن يؤدي إلى طريق مسدود أو جوع . ال مشكلة الفيلسوف لتناول الطعام يمكن النظر إليها على أنها تمثيل مباشر لعدد من العمليات، كل منها يتطلب موارد. نظرًا لأن كل عملية من هذه العمليات تتطلب تخصيص موارد، فمن الضروري توزيع هذه الموارد عبر جميع العمليات حتى لا تتعطل أي عملية أو تتوقف عن العمل.

افترض أن هناك خمسة فلاسفة يجلسون في مكان واحد طاولة على شكل دائرة . يأكلون في وقت ما ويفكرون في شيء ما في مكان آخر. حول المائدة المستديرة، يوزع الفلاسفة على الكراسي بشكل متساوٍ. بالإضافة إلى ذلك، يوجد وعاء من الأرز وخمسة عيدان لكل فيلسوف في منتصف الطاولة. عندما تشعر الفيلسوفة بأنها لا تستطيع التفاعل مع زملائها الجالسين بالقرب منها.

أحيانًا تتناول الفيلسوفة عيدان تناول الطعام عندما تشعر بالجوع. تختار عيدان تناول الطعام من جيرانها - واحدة عليها غادر وواحدة عليها يمين - التي تكون في متناول اليد. لكن لا ينبغي للفيلسوف أبدًا أن يلتقط أكثر من عيدان طعام واحدة في وقت واحد. من الواضح أنها لن تكون قادرة على التقاط عيدان تناول الطعام التي يستخدمها جارها.

نافذة.افتح جافا سكريبت

مثال:

دعونا نستخدم مثالاً لتوضيح كيفية تنفيذ ذلك في لغة C.

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

توضيح:

عيدان تناول الطعام يمكن تمثيلها بواسطة إشارة. لأن هناك عيدان تناول الطعام على الطاولة ولم يختر أي فيلسوف واحدًا، تتم تهيئة جميع مكونات عيدان تناول الطعام أولاً 1 . الآن ذلك عود الطعام[i] تم اختياره كأول عود. عود الطعام[i] و عود الطعام[(i+1)%5] تخضع لعملية الانتظار الأولى. هؤلاء عملية انتظار عيدان تناول الطعام يدل على أن الفيلسوف قد التقطهم. تبدأ عملية الأكل بمجرد أن يختار الفيلسوف طعامه عود . يتم الآن تنفيذ عملية الإشارة على عيدان تناول الطعام [i] و [(i+1)%5] بمجرد انتهاء الفيلسوف من الأكل. ثم يعود الفيلسوف إلى النوم.

لتحديد ما إذا كان موضوع فرعي انضم إلى الموضوع الرئيسي أم لا، استخدمنا وظيفة pthread_join . وبالمثل، فقد تحققنا مما إذا كان كائن المزامنة تمت تهيئة القفل باستخدام pthread_mutex_init طريقة.

للتهيئة والتحقق مما إذا كان مؤشر الترابط الجديد قد تم إنشاؤه أم لا، استخدمنا وظيفة pthread_create . وعلى نحو مماثل، قمنا بتدمير قفل كائن المزامنة باستخدام pthread_mutex_destroy وظيفة.

مشكلة المنتج والمستهلك:

هناك مشكلة شائعة تتعلق بمزامنة عملية مؤشرات الترابط المتعددة وهي مشكلة المنتج والمستهلك . وتوجد فيه عمليتان: الأولى هي عملية المنتج ، والثاني هو عملية المستهلك . علاوة على ذلك، من المفترض أن كلا العمليتين تحدثان بشكل متزامن بالتوازي. بالإضافة إلى ذلك، فهي عملية تعاونية، مما يعني أنهم يتقاسمون شيئًا ما مع بعضهم البعض. ومن المهم أنه عندما يكون المخزن المؤقت ممتلىء ، لا يمكن للمنتج إضافة البيانات. عندما يكون المخزن المؤقت فارغًا، لا يمكن للمستهلك استخراج البيانات من المخزن المؤقت لأن حجم المخزن المؤقت المشترك بين المنتج والمستهلك هو مُثَبَّت . وقد وردت المسألة بهذه الطريقة. ومن هنا، ولتنفيذ مشكلة المنتج والمستهلك وحلها، سنستخدم فكرة البرمجة الموازية.

مثال:

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

انتاج:

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

توضيح:

نقوم بمهمتين. وظائف مستهلك() و منتج() تشير إلى حالة وتشغيل مستهلك و منتج . ال طريقة المنتج (). سيتم إنشاء قفل كائن المزامنة وتحديد ما إذا كان المخزن المؤقت ممتلىء عندما يطلق عليه. عندما يمتلئ المخزن المؤقت، لن يتم إنتاج أي شيء. إذا لم يكن الأمر كذلك، فإنه سوف يخلق ، وبعد ذلك إنتاج ، سوف يضع نفسه في وضع السكون لفتح قفل الملف قفل كائن المزامنة . مثل ال منتج ، يقوم المستهلك أولاً بإنشاء قفل كائن المزامنة ، يتحقق من متعادل ، يستهلك منتج ، ثم قم بتحرير القفل قبل الرجوع إلى وضع السكون.

أ العداد (x) سيتم استخدامه أثناء التصنيع وسيستمر في النمو حتى تنتج الشركة المصنعة العنصر. ومع ذلك، فإن المستهلك سوف يصنع عددًا أقل من نفس المنتجات المصنعة البند (خ) .

خاتمة:

فكرة الاستخدام اثنين أو المزيد من المواضيع لتنفيذ برنامج يعرف باسم تعدد المواضيع في لغة البرمجة C. تعدد الخيوط يسمح بالتنفيذ المتزامن للعديد من المهام. أبسط عنصر قابل للتنفيذ في البرنامج هو خيط . هذه العملية هي فكرة أنه يمكن إكمال المهمة عن طريق تقسيمها إلى عدة أجزاء أصغر العمليات الفرعية .

ملف الرأس pthread.h مطلوب لتنفيذ تعدد مؤشرات الترابط في لغة C لأنه لا يمكن القيام به مباشرة.