Linux C + + multithreading "three"

Source: Internet
Author: User

Today Hollow continues to sweep (https://computing.llnl.gov/tutorials/pthreads/, this time not in C + +, direct reference to the C language in tutorial implementation Another method of thread synchronization provided in Pthread:condition variables

since there is already a mutex, why should have condition variables such technical means ?

The original description is: "While mutexes implement synchronization by controlling thread access to data, condition variables allow threads to Synchronize based upon the actual value of data. "

According to my own understanding is:

1) The role of the mutex is limited to whether a sub-thread is allowed to access, modify a memory variable to do so, the synchronize logic provided is limited to: can or cannot

2) The role of condition variables is stronger than that of a simple mutex and can be used in conjunction with mutexes; the synchronize mechanism provided can be: If condition then does work

The above understanding, but also I have achieved a demo after the conclusion, the following to explain the simple demo.

Consider a question like this:

1) There is a global count variable int count, each thread can access

2) There are two sub-threads that accumulate count

3) There is also a monitoring sub-thread that is sensitive to the value of Count: When Count is added to a threshold, the child thread is triggered to complete the task

The code is as follows:

#include <pthread.h>#include<stdio.h>#include<stdlib.h>#defineNum_threads 3#defineTCOUNT 10#defineCount_limit 12intCount =0;intthread_id[3] = {0,1,2};p thread_mutex_t count_mutex;pthread_cond_t COUNT_THRESHOLD_CV;void*inc_count (void*t) {    inti; Longmy_id = (Long) T;  for(i=0; i<tcount; i++) {Pthread_mutex_lock (&Count_mutex); Count++; if(count==count_limit) {Pthread_cond_signal (&COUNT_THRESHOLD_CV); printf ("inc_count (): Thread%ld, Count =%d Threshold reached \ n", my_id, Count); } printf ("inc_count (): Thread%ld, Count =%d, unlocking mutex \ n", my_id, Count); Pthread_mutex_unlock (&Count_mutex); Sleep (1); } pthread_exit ((void*)0);}void*watch_count (void*t) {    Longmy_id = (Long) T; printf ("starting Watch_count (): Thread%ld\n", my_id); Pthread_mutex_lock (&Count_mutex);  while(count<count_limit) {pthread_cond_wait (&AMP;COUNT_THRESHOLD_CV, &Count_mutex); printf ("watch_count (): Thread%ld Condition signale received.\n", my_id); Count+= the; printf ("watch_count (): Thread%ld count now =%d.\n", my_id, Count); } pthread_mutex_unlock (&Count_mutex); Pthread_exit ((void*)0);}intMainintargcChar*argv[]) {    intI, RC; Longt1=1, t2=2, t3=3; pthread_t threads[3];    pthread_attr_t attr; Pthread_mutex_init (&Count_mutex, NULL); Pthread_cond_init (&COUNT_THRESHOLD_CV, NULL); Pthread_attr_init (&attr); Pthread_attr_setdetachstate (&attr, pthread_create_joinable); Pthread_create (&threads[0], &attr, Watch_count, (void*) t1); Pthread_create (&threads[1], &attr, Inc_count, (void*) t2); Pthread_create (&threads[2], &attr, Inc_count, (void*) t3);  for(i=0; i<num_threads; ++i)    {Pthread_join (threads[i], NULL); } printf ("Main (): Waited on%d threads. Done. \ n", num_threads); Pthread_attr_destroy (&attr); Pthread_mutex_destroy (&Count_mutex); Pthread_cond_destroy (&COUNT_THRESHOLD_CV); Pthread_exit ((void*)0);}

First give the output, and then explain how this code to achieve the above problem:

Two seed Threads:

1) void *inc_count (void *t) implements the cumulative count function for the global variable count

2) void *watch_count (void *t) implements the ability to monitor the value of the global variable count and trigger the task

The following records my own thought sequence for analyzing the implementation logic of each child thread:

1) watch_count count is monitored:

1 void*watch_count (void*t)2 {3     Longmy_id = (Long) T;4printf"starting Watch_count (): Thread%ld\n", my_id);5 6Pthread_mutex_lock (&Count_mutex);7      while(count<count_limit)8     {9Pthread_cond_wait (&AMP;COUNT_THRESHOLD_CV, &Count_mutex);Tenprintf"watch_count (): Thread%ld Condition signale received.\n", my_id); OneCount + = the; Aprintf"watch_count (): Thread%ld count now =%d.\n", my_id, count); -     } -Pthread_mutex_unlock (&Count_mutex); thePthread_exit ((void*)0); -}

A. Why is Line 6 locked to Count_mutex first?

Because, when Watch_count is judging the value of count, it must " monopolize " The operation right of count, and if count is changed by another thread or whatever, the logic is probably wrong ( This is explained in the previous logs in this series )

B. "pthread_cond_wait (&COUNT_THRESHOLD_CV, &count_mutex);" What is the role?

First, the following parameters are explained:pthread_cond_t COUNT_THREASHOLD_CV is the condition variable mentioned in this section; Count_mutex is the synchronous lock used for the global variable count

This statement is equivalent to doing two things as follows:

B1. Block the current thread first

B2. Determine if the COUNT_THRESHOLD_CV condition variable is activated:

B21. If not activated, automatically release the lock on the Count_mutex (this unlocking is for the lock on line 6 to Count_mutex); When the front thread continues to remain blocked

B22. If activated, the Count_mutex lock is awakened; The current thread is not blocked and continues to execute (since line 6 locks the current thread, it needs to unlock the Count_mutex before the thread is finished)

C. After reading the above code, two questions are immediately generated:

C1. COUNT_THRESHOLD_CV the initial state of the activation is not activated who tube?

Is "pthread_cond_init (&COUNT_THRESHOLD_CV, NULL)in the main () function; Statement, initialization COUNT_THRESHOLD_CV not activated.

C2. Who cares about the activation of COUNT_THRESHOLD_CV?

This is going to re-analyze another sub-thread function Inc_count.

2) Inc_count sub-thread adds count to & activates the condition variable COUNT_THRESHOLD_CV

1 void*inc_count (void*t)2 {3     inti;4     Longmy_id = (Long) T;5 6      for(i=0; i<tcount; i++){7Pthread_mutex_lock (&Count_mutex);8count++;9         if(count==count_limit)Ten         { OnePthread_cond_signal (&COUNT_THRESHOLD_CV); Aprintf"inc_count (): Thread%ld, Count =%d Threshold reached \ n", my_id, count); -         } -printf"inc_count (): Thread%ld, Count =%d, unlocking mutex \ n", my_id, count); thePthread_mutex_unlock (&Count_mutex); -Sleep1); -     } -Pthread_exit ((void*)0); +}

This function is more intuitive:

1) Count plus 1 for each time in loop ( of course, the operation of Count must be on the Count_mutex lock, line 7 statement )

2) determine the value of Count:

A. If count is not equal to a critical value: do some the work and unlock the Count_mutex; and then sleep again ( the goal is to manually give other threads the chance to gain Count_mutex control )

B. If count equals a critical value:

B1. Activating the condition variable COUNT_THRESHOLD_CV

B2. Wake up a thread that is blocked by waiting for COUNT_THRESHOLD_CV ( there is only one waiting thread in this demo, if multiple threads are waiting for COUNT_THRESHOLD_CV?). This is worth thinking about later .)

B2 has a detail problem: when COUNT_THRESHOLD_CV is activated, Watch_count is executed immediately? Or are you waiting for the thread to activate COUNT_THRESHOLD_CV to be " really " woken up after execution? To speak with the result:

Obviously, even after the COUNT_THRESHOLD_CV is activated, Watch_count does not execute immediately, but waits for the Count_mutex in the Inc_count to be unlocked and then executes the watch_count thread that was awakened by the excitation; Watch_ The count thread was awakened while the Watch_count thread regained the Count_mutex's possession.

The above demo has probably explained how condition variables is used, and there are several details that should be deducted:

Details One :

There is actually still a place not quite sure: for example, when COUNT_THRESHOLD_CV was activated by THREAD3, and THREAD3 thread has performed unlocking on Count_mutex, Is there a situation where Thread1 (Thread1 is Watch_count thread) and Thread2 (Thread2 is another inc_count thread) compete Count_mutex at the same time ? According to the results of the output, there may be no thread1 and thread2 competition, the operating system gives the awakened thread1 to the Count_mutex priority lock.

Detail Two :

If there are no restrictions on Count_mutex in the thread that calls Pthread_cond_wait, then what is the result of the operation? I fixed a little bit of code, added a global pthread_mutex_t test, initialized it in main, and modified the Inc_count function and Watch_count function as follows (red is the modified part):

void*inc_count (void*6) {    inti; Longmy_id = (Long) T;  for(i=0; i<tcount; i++) {Pthread_mutex_lock (&Count_mutex); Count++; if(count==count_limit) {Pthread_cond_signal (&COUNT_THRESHOLD_CV); Sleep ( 1); printf ("inc_count (): Thread%ld, Count =%d Threshold reached \ n", my_id, Count); } printf ("inc_count (): Thread%ld, Count =%d, unlocking mutex \ n", my_id, Count); Pthread_mutex_unlock (&Count_mutex); Sleep (1); } pthread_exit ((void*)0);}void*watch_count (void*t) {    Longmy_id = (Long) T; printf ("starting Watch_count (): Thread%ld\n", my_id); Pthread_mutex_lock ( &test); intI=0;  while(i<1) { pthread_cond_wait ( &COUNT_THRESHOLD_CV, & test); printf ("watch_count (): Thread%ld Condition signale received.\n", my_id); Count+= the; printf ("watch_count (): Thread%ld count now =%d.\n", my_id, Count); I++; } Pthread_mutex_unlock ( & test); Pthread_exit ((void*)0);}

The results of the operation are as follows:

With this result, you can see: Once pthread_cond_signal, because there is no count_mutex lock limit, the Watch_count thread executes immediately (here in the Inc_count function added sleep (1) is deliberately waiting, See if Watch_count is not immediately blocked from being executed). As a result, it is verified again from the opposite side that the thread calling pthread_cond_signal is simply sending a signal to activate the watch_count thread; If the watch_count is restricted by Count_mutex, wait until inc_ The Count_mutex is unlocked in count before it is actually activated.

The following two connections, the pthread_cond_wait () and pthread_cond_signal () have a more detailed explanation

Https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_wait.txt

Https://computing.llnl.gov/tutorials/pthreads/man/pthread_cond_signal.txt

But in the actual work, still have to test the code to run the platform system, to pthread is how a concrete implementation strategy.

   

Linux C + + multithreading "three"

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.