In the previous article, we mainly explained the basic concepts and features of multithreading in Linux environment, this article will explain the synchronization mode of multithreading in Linux environment.
In the second edition of the UNIX Environment Advanced Programming, Chapter 11th threads, mentions three basic synchronization mechanisms in Unix-like systems : Mutex, read-write lock, condition variable . The following are descriptions of these three mechanisms:
One, thread mutex
Mutual exclusion implies "exclusive", that is, two threads cannot enter mutually exclusive protected code at the same time. Linux can be defined by the pthread_mutex_t mutex mechanism to complete the multi-threaded mutex, the role of the mechanism is to a mutually exclusive part, in the first to obtain a mutex, if not get the mutex, that the mutex is owned by other threads, at this time to get the mutex thread blocking, Until the thread that owns the mutex completes the mutex operation. The operation functions of the mutex include:
#include <pthread.h>int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t, *mutexattr); int Pthread_mutex_lock (pthread_mutex_t *mutex); int Pthread_mutex_unlock (pthread_mutex_t *mutex); int pthread_mutex_ Destory (pthread_mutex_t *mutex);
As with other functions, these functions return 0 when they succeed, and error codes are returned when they fail, but these functions do not set errno, so the return code of the function must be checked. Here is an example of how to use:
#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <String.h>void *thread_function (void *ARG);Char message[] ="Hello World";IntMain () {IntRes pthread_t A_thread;void *Thread_result; res = Pthread_create (&a_thread, NULL, Thread_function, (void *) message);if (res! =0) {perror ("Thread Creation failed!"); Exit (Exit_failure); } printf ("Waiting for thread to finish.../n"); res = Pthread_join (A_thread, &Thread_result);if (res! =0) {perror ("Thread Join failed!/n"); Exit (Exit_failure); } printf ("Thread joined, it returned%s/n", (char *) thread_result); printf"Message is now%s/n "void *thread_function (void * arg) {printf ( "thread_function is running. Argument was%s/nchar * 3 "bye!" "thank you for your CPU Time! "
The compilation statements are:
Gcc-d_reentrant Thread4.c-o Thread4–lpthread
The result of the operation is:
$./thread2input some text. Enter ' End ' to finish123you input 3 characters1234you input 4 characters12345you input 5 charactersendyou input 3 characte Rsthread joined
second, read and write lock
Read and write locks are similar to mutexes, but read-write locks allow for higher parallelism. The mutex is either locked or unlocked, and only one thread can lock it at a time. and read-write lock has three kinds of states: Read mode lock state, write mode lock state, no lock state. Only one thread at a time can occupy write-mode read-write locks, but there can be multiple threads concurrently occupying read-mode reading and writing locks.
Although there are many different ways to implement a read-write lock, a read-write lock usually blocks subsequent read-mode lock requests if another thread attempts to write-mode locks when the read-write lock is locked, which avoids the long-term use of the reading-mode locks and waits for write-mode lock requests to remain unmet.
Read-write locks are also called shared-exclusive locks, and read-write locks are well suited for reading data structures much more frequently than write times. The interface functions for read and write locks include the following:
2.1 Creating and destroying
#include <pthread.h>int pthread_rwlock_init (pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t * Restrict attr), int Pthread_rwlock_destroy (pthread_rwlock_t *rwlock), Success returns 0, error number is returned.
2.2 read locking and write plus lock
#include <pthread.h>int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); int Pthread_rwlock_wrlock (Pthread_ rwlock_t *rwlock); int Pthread_rwlock_unlock (pthread_rwlock_t *rwlock); Success returns 0, error number is returned.
2.3 Non-blocking access to read-write locks
#include <pthread.h>int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock); int Pthread_rwlock_trywrlock ( pthread_rwlock_t *rwlock), Success returns 0, error number is returned.
three, condition variable
A condition variable is another synchronization mechanism available to a thread. A condition variable provides a rendezvous place for multiple threads. The condition variable is used in conjunction with the mutex, allowing the thread to wait for a particular condition to occur in a non-competitive manner, which itself is protected by a mutex variable. The thread must lock the mutex before changing the condition state, and the other thread will not be aware of the change until the mutex is acquired, because it must be locked before the condition can be evaluated.
The action function for a condition variable includes the following:
3.1 Creating and destroying
#include <pthread.h>int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr); int Pthread_ Cond_destroy (pthread_cond_t *cond);
3.2 Items to wait
#include <pthread.h>int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); int Pthread_cond_ Timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec* timeout);
With pthread_cond_wait you can wait for the condition to become true, the mutex passed to the pthread_cond_wait protects the condition, the caller passes the locked mutex to the function, the function puts the calling thread on the list of threads waiting for the condition, and then unlocks the mutex. These two operations are atomic operations. This turns off the time channel between the condition check and the thread going into hibernation waiting for the condition to change, so that the thread does not miss any changes to the condition. When the pthread_cond_wait returns, the mutex is locked again.
3.3 Notification conditions
#include <pthread.h>int pthread_cond_broadcast (pthread_cond_t *cond); int pthread_cond_signal (pthread_cond_t * COND);
These two functions can be used to inform the thread that the condition has been met, Pthread_cond_signal will wake up a thread waiting for the condition, and Pthread_cond_broadcast will wake up all the threads waiting for the condition.
Iv. Signal Volume
By the way, the semaphore defined in the header file <semaphore.h> completes the encapsulation of the mutex and the conditional variable, and according to the access control mechanism in the multi-thread program design, controls the synchronization access to the resource, and provides a more convenient calling interface for the programming designer. Its function interface is as follows:
#include <semaphore.h>int sem_init (sem_t *sem, int pshared, unsigned int val); int sem_wait (sem_t *sem); int Sem_post (sem_t *sem);
The semaphore is essentially a nonnegative integer counter that is used to control access to public resources. Each call to the wait operation will cause the semaphore value to be reduced by 1, and if the semaphore value is already 0, the wait operation will be blocked. Each time the post operation is called, the semaphore value is added 1.
The semaphore differs from the thread lock and condition variable in the following ways:
(1) The lock must be the same thread to get and release, otherwise it will deadlock. The condition variables and semaphores do not have to be.
(2) The signal increment and decrease will be automatically remembered by the system, there is a counter inside the system to achieve the semaphore, do not have to worry about loss, and when a condition variable is awakened, if there is no corresponding thread waiting for the condition variable, this wake will be lost.
Example of how far analog signal volume
As you can see from the previous section, Pthread only provides mutex and conditional variables for thread mutexes, while read-write locks are used for multiple read and write-less applications. The following is an example of "producer/consumer issues" to illustrate the control and communication of Linux threads. A set of producer threads is associated with a set of consumer threads through a buffer. The producer thread feeds the produced product into a buffer and the consumer thread extracts the product from it. The buffer has n and is a ring buffer pool.
View Code
Multithreading in Linux environments with multithreaded programming (II.)