1. Introduction to Mutual exclusion lock
Mutexes are primarily used for mutual exclusion, which is a competitive relationship that is used to protect critical resources from being accessed by only one thread at a time.
POSIX Pthread provides the following functions for manipulating mutex locks.
int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr); int pthread_mutex_lock (pthread_mutex_t *mutex); int pthread_mutex_trylock (pthread_mutex_t *mutex); int pthread_mutex_unlock (pthread_mutex_t *mutex); int Pthread_mutex_destroy (pthread_mutex_t *mutex); //return://Pthread_mutex_init always returns 0//the other mutex function returns 0 for success, not 0 for error codes that fail
#define CHECK (exp) if (!exp) { fprintf (stderr, "file:%s, line:%d exp:[" #exp "] is true, abort.\n", __file__, __LINE__); Abort (); }
Since the Pthread series function returns 0 when it succeeds, we can write a macro as a lightweight checking method to determine the processing error.
The actual use of the time only:CHECK(!pthread_mutex_lock(&mutex));
2. Encapsulation of mutual exclusion lock
Here are a few questions to consider:
A. The initialization and destruction of the mutex.
B. Operation of the mutex: locking and Release lock.
In addition, our own encapsulated classes should not have the semantics of assignment and copy constructs, which, like the singleton pattern, allows our classes to inherit from the noncopyable of the boost library.
//mutexlock.h#ifndef __MUTEXLOCK_H__# Define __mutexlock_h__#include <iostream> #include <cstdio> #include <boost/noncopyable.hpp># Include <pthread.h> #include <assert.h> #define CHECK (exp) if (!exp) {fprintf (stderr, "file:%s, line:%d exp:["#exp"] is true, abort.\n ", __file__, __line__); Abort ();} Class Mutexlock:public boost::noncopyable{friend class condition;//conditional variable friend declaration public:mutexlock (); ~mutexlock (); void Lock (); void unlock (); BOOL Islocking () const {return islocking_; } pthread_mutex_t *getmutexptr () {return &mutex_; } private:void Restoremutexstatus () {islocking_=true; } pthread_mutex_t mutex_;//mutex bool islocking_;}; #endif
This completes the declaration of the Mutexlock class, but there is a need to add that using raii (resource acquisition is initialized) technology, Handling of Mutexlock initialization and destruction: When initializing is unlocked, when the destructor is unlocked, we need to redefine a class Mutexlockguard to operate on the Mutexlock
class mutexlockguard: public boost::noncopyable{ public : Mutexlockguard (Mutexlock &mutex): mutex_ (Mutex) {Mutex_. Lock ();} // construct with lock ~mutexlockguard () // destructor unlocked Unlock (); private : Mutexlock &mutex_;//Note why this is a reference!!!! };
Here are the specific implementation of several functions, mainly:
pthread_mutex_init(),,, and the pthread_mutex_destroy() pthread_mutex_lock() pthread_mutex_unlock() encapsulation of these four functions:
#include"MutexLock.h"Mutexlock::mutexlock (): Islocking_ (false) {CHECK (!pthread_mutex_init (&mutex_,null));} Mutexlock::~Mutexlock () {Assert (!islocking ()); CHECK (!pthread_mutex_destroy (&mutex_));}
voidMutexlock::Lock() {CHECK (!pthread_mutex_lock (&mutex_))//first Lock and then modify the state to ensure the atomicity of the following assignment operation. islocking_=true;}voidMutexlock::unlock () {Islocking_=false;//first, the state is unlocked to ensure the atomicity of the assignment operation. CHECK (!pthread_mutex_unlock (&mutex_));}
After encapsulation, we use:
MutexLockGurad lock(mutex);//就是 MutexLock对象被另一个对象管理
对临界区进行加锁,而只要我们控制好lock变量的生存期,就能控制临界区,例如:
int count=0; { Lock (mutex); Count+ +;} //critical section // ... // leave the scope of lock, lock as a variable on the stack, automatically release, call the destructor, and release the lock.
C + + package line libraries 0