LINUX multi-thread programming (pthread Library) study Note 3

Source: Internet
Author: User

Mutex lock for processing data of threads

Mutex lock

Mutex lock is used to ensure that only one thread is executing a piece of code within a period of time.
The pthread_mutex_lock statement starts to lock with mutex lock. Subsequent code is locked until pthread_mutex_unlock is called, that is, only one thread can call and execute the lock at a time. When a thread executes at pthread_mutex_lock, if the lock is used by another thread at this time, the thread is blocked, that is, the program will wait for another thread to release the mutex lock.

 

Thread a First locks mutex lock 1, thread B First locks mutex lock 2, then a deadlock occurs. In this case, we can use the function pthread_mutex_trylock, which is a non-blocking version of the function pthread_mutex_lock. When it finds that a deadlock is inevitable, it will return the corresponding information, and the programmer can handle the deadlock accordingly. In addition, different mutex lock types have different deadlocks, but the most important thing is that programmers should pay attention to this in programming.

 

Condition variable
An obvious disadvantage of mutex is that it has only two States: Locked and non-locked. Conditional variables make up for the lack of mutex lock by allowing the thread to block and wait for another thread to send signals. They are often used together with mutex locks. When a condition variable is used to block a thread, when the condition is not met, the thread often unlocks the corresponding mutex and waits for the condition to change. Once another thread changes the condition variable, it will notify the corresponding condition variable to wake up one or more threads that are blocked by this condition variable. These threads will re-lock the mutex and re-test whether the conditions are met. Generally, condition variables are used for synchronization between threads.

The condition variable structure is pthread_cond_t.,The pthread_cond_init () function is used to initialize a condition variable.. Its prototype is:
Extern int pthread_cond_init _ p (pthread_cond_t * _ cond,

_ Const pthread_condattr_t * _ cond_attr ));
Cond is a pointer to the structure pthread_cond_t, and cond_attr is a pointer to the structure pthread_condattr_t.

The structure pthread_condattr_t is the attribute structure of the condition variable. Like the mutex lock, we can use it to set whether the condition variable is available in the process or between processes. The default value is pthread _ process_private, this condition variable is used by various threads in the same process. Note that the initialization condition variables can be reinitialized or released only when they are not used.

The function for releasing a condition variable is pthread_cond _ destroy (pthread_cond_t Cond ).

The pthread_cond_wait () function blocks the thread on a condition variable. Its function prototype is:
Extern int pthread_cond_wait _ p (pthread_cond_t * _ cond,
Pthread_mutex_t * _ mutex ));
The thread unlocks the lock pointed to by mutex and is blocked by the condition variable cond. The thread can be awakened by the pthread_cond_signal function and the pthread_cond_broadcast function, but note that,The condition variable only serves to block and wake up the thread. The user still needs to give the specific judgment ConditionFor example, whether a variable is 0. We can see this in the following example. After the thread is awakened, it will re-check whether the conditions are met. If the conditions are not met, the thread should still be blocked here and be waiting for the next wake-up. This process is generally implemented using the while statement.

Another function used to block threads is pthread_cond_timedwait (). Its prototype is:
Extern int pthread_cond_timedwait _ p (pthread_cond_t * _ cond,
Pthread_mutex_t * _ mutex,

_ Const struct timespec * _ abstime ));
It has one more time parameter than the pthread_cond_wait () function. After a period of time in abstime, blocking is also removed even if the condition variable is not met.

 

The prototype of the function pthread_cond_signal () is:
Extern int pthread_cond_signal _ p (pthread_cond_t * _ Cond ));
It is used to release a thread that is blocked on the condition variable cond. When multiple threads are blocked on this condition variable, which thread is awakened is determined by the thread's scheduling policy. Note that the mutex lock of the Protection Condition variable must be used to protect this function. Otherwise, the signal that the condition satisfies may be sent between the test condition and the call of the pthread_cond_wait function, resulting in unlimited waiting.

 

The following is a simple example of using the functions pthread_cond_wait () and pthread_cond_signal.

# Include <iostream>
# Include <unistd. h>
# Include <pthread. h>
# Include <stdio. h>
Using namespace STD;

Pthread_mutex_t count_lock;
Pthread_cond_t count_nonzero;
Int counter = 0;
Int estatus =-1;

Void * decrement_count (void * argv );
Void * increment_count (void * argv );

Int main (INT argc, char * argv [])
{
Printf ("counter: % d \ n", counter );
Pthread_t thrd1, thrd2;
Int ret;
Ret = pthread_create (& thrd1, null, decrement_count, null );
If (RET)
{
Perror ("de1 :");
Return 1;
}
 
Ret = pthread_create (& thrd2, null, increment_count, null );
If (RET)
{
Perror ("in1 :");
Return 1;
}

Int COUNT = 0;
While (count! = 20)
{
Printf ("counter: % d \ n", counter );
Sleep (1 );
Count ++;
}
Return 0;
}

Void * decrement_count (void * argv)
{
Pthread_mutex_lock (& count_lock );
While (counter = 0)
Pthread_cond_wait (& count_nonzero, & count_lock );
Counter --;
Pthread_mutex_unlock (& count_lock );
Return & estatus;
}

Void * increment_count (void * argv)
{
Pthread_mutex_lock (& count_lock );
If (counter = 0)
Pthread_cond_signal (& count_nonzero );
Counter ++;
Pthread_mutex_unlock (& count_lock );
Return & estatus;
}

 

At the beginning, counter is 0, ret = pthread_create (& thrd1, null, decrement_count, null), and a thrd1 thread is generated to run decrement_count (). The function running process in this thread is: lock the mutex count_lock. If counter is 0, this thread is blocked on the condition variable count_nonzero. at the same time, the mutual exclusion lock count_lock is released.

 

At the same time, the main program is still running. Create another thread thrd2 to run increment_count. The function flow in this thread is as follows: Lock the mutex lock count_lock. If counter is 0, the thread on the condition variable count_nonzero is thrd1. but thrd1 is still waiting because of the mutex count_lock. then count ++ releases the mutex lock ,....... due to the release of the mutex lock, thrd1 re-judges whether the counter is 0. If it is 0, the thread is blocked on the condition variable count_nonzero, but the counter is already 1. so the thread continues to run. counter -- release the mutex ...... the counter runs for a period of time and exits.

 

Note: Add-lpthread during compilation.

 

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.