The difference between mutex, semaphore, condition variable

Source: Internet
Author: User
Tags posix semaphore

From: http://blog.chinaunix.net/space.php?uid=23061624&do=blog&cuid=2127853

Semaphores are used in multi-threaded multitasking, where one thread completes an action by telling another thread about the semaphore, and the other thread is doing some action (where everyone is blocking when semtake). The mutex is used in multi-threaded multitasking mutex, one thread occupies a certain resource, then other threads will not be able to access it, until the thread unlock, other threads will start to take advantage of this resource. For example, the access to global variables, sometimes to lock, the operation is finished, in the unlock. Sometimes the locks and semaphores are used simultaneously.
That is, the semaphore is not necessarily locked a certain resource, but the concept of the process, such as: There is a A, a, a two thread, B thread to wait for a thread to complete a task after the next step, the task does not necessarily lock a resource, but also to do some calculation or data processing and so on. The thread mutex is the concept of "lock a Resource", during which other threads cannot manipulate the protected data. In some cases the two are interchangeable.

The difference between the two:

Scope
Semaphores: Process or line threads (Linux threads only)
Mutex: Between threads

When locked
Semaphore: As long as the semaphore value is greater than 0, other threads can sem_wait success, and the value of the semaphore is reduced by one after success. If value is not greater than 0, then sem_wait blocks until Sem_post is released and the value
Mutex: No other thread can access the protected resource as long as it is locked

If it succeeds, it will block.

Here are some concepts of Semaphore (volume):

The main difference between a semaphore and a mutex and a condition variable is the concept of "light", which means that the resource is available and the light off means it is unavailable. If the latter two-way focus on the "wait" operation, that is, the resource is not available, the beacon mechanism is focused on lighting, that is, to inform the resource is available, there is no waiting for the thread to unlock or excitation conditions are meaningless, and not waiting for the light to light the lighting operation is valid, and can keep the light state. Of course, such an operation primitive also means more overhead.

The application of signal lights in addition to lights/lights out of this binary lamp, can also use more than 1 lamp number, to indicate that the number of resources greater than 1, this can be called multi-lamp.

1. Create and unregister

The POSIX beacon Standard defines both the famous and nameless lights, but the linuxthreads implementation is only nameless lights, while the famous lights in addition to always can be used between the process, in use with the nameless lamp is not very different, so the following is only the nameless lights discussed.

int Sem_init (sem_t *sem, int pshared, unsigned int value)
This is the API that creates the semaphore, where value is the initial value of the semaphore, and pshared indicates whether it is a multi-process share and not just a process. Linuxthreads does not implement a multi-process shared semaphore, so all pshared inputs that are not 0 values will cause sem_init () to return 1, with the errno set to Enosys. The well-initialized signals are characterized by SEM variables and are used for the following illumination and lamp operation.

int Sem_destroy (SEM_T * sem)
The log off of the semaphore SEM requires that no thread is waiting for the semaphore, otherwise it returns-1, and the errno is ebusy. In addition, Linuxthreads's semaphore logoff function does not perform other actions.

2. Lighting and extinguishing lights

int sem_post (SEM_T * sem)

The lighting operation adds 1 to the beacon value, indicating an additional accessible resource.

int sem_wait (SEM_T * sem)
int sem_trywait (SEM_T * sem)

Sem_wait () waits for the light to light up, waits for the light to light (the semaphore value is greater than 0), and then the semaphore is atomically reduced by 1 and returned. Sem_trywait () is a non-blocking version of Sem_wait (), and if the semaphore count is greater than 0, the atom is reduced by 1 and returns 0, otherwise the -1,errno is immediately returned to Eagain.

3. Get lamp value

int Sem_getvalue (SEM_T * sem, int * sval)

Reads the lamp count in the SEM, is stored in the *sval, and returns 0.

4. Other

Sem_wait () is implemented as a cancellation point, and Sem_post () is the only API for POSIX asynchronous signal security that can be used for asynchronous signal processing functions on architectures that support atomic "compare and swap" directives.

----------------------------
Thread synchronization: When mutexes are not enough, do you need a condition variable?

Assuming there is a shared resource sum, the mutex associated with it is lock_s. It is assumed that each thread's operation on sum is simple, regardless of the state of sum, such as just sum++. Then only the mutex is sufficient. Programmers just make sure that each thread is operational before it gets lock, and then sum+ +, then unlock. The code for each thread will look like this
Add ()
{
Pthread_mutex_lock (lock_s);
sum++;
Pthread_mutex_unlock (lock_s);
}

If the operation is complicated, assuming that the thread t0,t1,t2 operation is sum++, and the thread T3 is the time when sum reaches 100, a message is printed and the sum is cleared 0. In this case, if only the mutex is used, then the T3 needs a loop, lock_s is obtained in each loop, then the state of sum is checked, and if sum>=100 is printed and zeroed, then unlock. if sum& amp; lt;100, then unlock, and sleep () this thread is appropriate for a period of time.

At this time, T0,t1,t2 's code does not change, T3 's code is as follows
Print ()
{
while (1)
{
Pthread_mutex_lock (lock_s);
if (sum<100)
{
printf ("Sum reach 100!");
Pthread_mutex_unlock (lock_s);
}
Else
{
Pthread_mutex_unlock (lock_s);
My_thread_sleep (100);
return OK;
}
}
}

There are two problems with this approach
1) sum in most cases will not reach 100, then for T3 code, most of the time, go to the Else branch, just lock and unlock, and then sleep (). This wastes CPU processing time.
2) to save CPU processing time, T3 will sleep () for a period of time when it detects that sum does not reach 100. This brings another problem, that is, the T3 response slows down. Maybe T4 will wake up when sum reaches 200.
3) In this way, the programmer in the Set sleep () time in a dilemma, set too short to save resources, too long and slow down the response. It's really hard.

This time, condition variable underwear outside wear, fell from the sky, saved the burned you.

You first define a condition variable.
pthread_cond_t Cond_sum_ready=pthread_cond_initializer;

T0,t1,t2 's code just adds two lines to the back, like this.
Add ()
{
Pthread_mutex_lock (lock_s);
sum++;
Pthread_mutex_unlock (lock_s);
if (sum>=100)
Pthread_cond_signal (&cond_sum_ready);
}
and the T3 code is
Print
{
Pthread_mutex_lock (lock_s);
while (sum<100)
Pthread_cond_wait (&cond_sum_ready, &lock_s);
printf ("Sum is over 100!");
sum=0;
Pthread_mutex_unlock (lock_s);
return OK;
}

Note two points:
1) before thread_cond_wait (), you must first lock the mutex associated with it, because if the target condition is not met, pthread_cond_wait () will actually unlock the mutex, then block, Lock the mutex again after the target condition is satisfied, and then return.
2) Why is while (sum<100), not if (sum<100)? This is because there is a time difference between pthread_cond_signal () and pthread_cond_wait (), assuming that within this time difference, There is another thread T4 and the sum reduced to less than 100, then T3 after the return of Pthread_cond_wait (), it is clear that the sum of the size should be checked again. That's what you use while.

The difference between mutex, semaphore, condition variable

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.