The difference between recursive mutex and common mutex is explained by the test program under Linux.

Source: Internet
Author: User
Tags function definition mutex pthread mutex

Tag: Item strong error code print Erro code Err Status Count

Post code and test results first

//Mutex.h: Raii wrapper for Pthread mutex#ifndef _mutex_h_#define_mutex_h_#include<stdio.h>#include<stdlib.h>#include<string.h>#include<pthread.h>//Use error code Errnum and string msg to print error messages and exit the programStaticInlinevoidErrexiten (intErrnum,Const Char*msg) {fprintf (stderr,"%s Error:%s\n", MSG, strerror (errnum)); Exit (1);}classmutex{ Public:    ExplicitMutex () {ints;        pthread_mutexattr_t attr; S= Pthread_mutexattr_init (&attr); if(s! =0) Errexiten (S,"Pthread_mutexattr_init"); S= Pthread_mutexattr_settype (&attr, Pthread_mutex_default); #ifdef Errorcheck s= Pthread_mutexattr_settype (&attr, Pthread_mutex_errorcheck);#elifRECURSIVEs= Pthread_mutexattr_settype (&attr, pthread_mutex_recursive);#endif        if(s! =0) Errexiten (S,"Pthread_mutexattr_settype"); Pthread_mutex_init (&AMP;__MTX, &attr); if(s! =0) Errexiten (S,"Pthread_mutex_init"); S= Pthread_mutexattr_destroy (&attr); if(s! =0) Errexiten (S,"Pthread_mutexattr_destroy"); }    Virtual~Mutex () {ints = Pthread_mutex_destroy (&__mtx); if(s! =0) Errexiten (S,"Pthread_mutex_destroy"); }    void Lock()    {        ints = Pthread_mutex_lock (&__mtx); if(s! =0) Errexiten (S,"Pthread_mutex_lock"); }    voidunlock () {ints = Pthread_mutex_unlock (&__mtx); if(s! =0) Errexiten (S,"Pthread_mutex_unlock"); }Private: pthread_mutex_t __mtx;};#endif
//MutexTest.cpp:Mutex class for repeated acquisition of the same lock test#include"Mutex.h"#include<stdio.h>#include<pthread.h>#include<array>Mutex Mtx;std::array<int,Ten>G_array;//increment (protect with mutex) the element to the left of G_array[index]voidIncrleftwithmutex (intindex) {MTX.Lock();  for(inti =0; I < index; i++) G_array[i]++; Mtx.unlock ();}//increment the element to the right of G_array[index] (protected with mutex)voidIncrrightwithmutex (intindex) {MTX.Lock();  for(inti = index +1; I < (int) G_array.size (); i++) G_array[i]++; Mtx.unlock ();}//add an element other than G_array[index]voidIncrotheritem (intindex) {MTX.Lock();    Incrleftwithmutex (index);    Incrrightwithmutex (index); Mtx.unlock ();}intMain () {G_array.fill (0); Incrotheritem (5);  for(inti:g_array) printf ("%d", i); printf ("\ n"); return 0;}
$ g++ mutextest.CPP-std=c++ One-pthread$ Time./a.out^creal 0m3.973suser 0m0.004ssys 0m0.000s$ g+ + Mutextest.CPP-std=c++ One-pthread-derrorcheck$./a.out pthread_mutex_lock error:resource deadlock Avoidedpthread_mutex_destroy error:device or Resource busy$ g+ + Mutextest.CPP-std=c++ One-pthread-drecursive$./a.out1 1 1 1 1 0 1 1 1 1 

No additional defined macros use the default mutex (lock), the definition macro Errorcheck the lock comes with error checking, and the definition macro recursive represents a recursive lock.

The main thread calls the Incrotheritem function, which first acquires (acquire) the lock MTX and then calls the other 2 functions to release the (release) lock of MTX.

The experimental results show that the default lock is stuck in a deadlock, and the result of the error check is resource deadlock avoided (which is stuck in a deadlock), and the recursive lock executes successfully.

The thread blocks until a lock has been acquired and the lock is freed by a lock request. So if a thread has acquired lock A and is not released, when it acquires lock a again, it gets stuck in a deadlock, because the thread blocks until lock A is released, and then only the thread that owns the lock (that is, itself) can release the lock, and the thread itself is blocked, so it is always in a blocking state.

Recursive locking is to solve this situation, the function definition from Incrotheritem looks like the code has no problem, but the Incrleftwithmutex and Incrrightwithmutex functions try to acquire the same lock, This is equivalent to not releasing the lock and acquiring the same lock again.

A recursive lock maintains a counter internally, and when the thread obtains the mutex for the 1th time, the counter is set to 1, after which the thread can get the same lock, each time acquiring the lock counter plus 1, and each release lock counter minus 1. Because other threads cannot acquire the lock at this point, the code is fine as long as the thread's execution is guaranteed to be reentrant .

Because this is often the case when a function is called recursively, such as

Function 1: Lock, call function 2, unlock.

Function 2: Lock ... Unlock

The process of function 1 becomes: lock, function 1 content (first part), lock, function 2 contents, unlock, Function 1 contents (Part Two), unlock.

If the contents of function 1 are not reentrant, and function 2 modifies the operand of function 1, there will be a problem here.

Like what. The function 1 is to get the sum of the global int array (set to int a[4] = {1,2,3,4}), the first part is for the first half, and the second part is for the last half part.

And if the function 2 causes the int array to change, for example lets a[2] = 0, so that finally obtains is 1+2+0+4=7 instead of 1+2+3+4=10.

The difference between recursive mutex and common mutex is explained by the test program under Linux.

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.