前言:

相信需要了解这方面的知识的小伙伴,已经基本对进程间通信和线程间通信有了一定了解。例如,进程间通信的机制之一:共享内存(在这里不做详解):多个进程可同时访问同一块内存。如果不对访问这块内存的临界区进行互斥或者同步,那么进程的运行很可能出现一些不可预知的错误和结果。

接下来我们了解三种常见的Linux下的互斥操作—>锁。

1.互斥锁(mutex)

特点:对于读者和写者来说。只要有一方获取了锁,另一方则不能继续获取,进而执行临界区代码。

创建锁:

有两种方法创建互斥锁,静态方式和动态方式。POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER 来静态初始化互斥锁,

方法如下:

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。

动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t*mutexattr)

其中mutexattr用于指定互斥锁属性(见下),如果为NULL则使用缺省属性。 pthread_mutex_destroy ()用于注销一个互斥锁,API定义如下:

int pthread_mutex_destroy(pthread_mutex_t *mutex)

锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到, 而必须等待解锁。对于普通锁和适应锁类型,解锁者可以是同进程内任何线程; 而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由 加锁者解锁,但实验结果表明并没有这种限制,这个不同目前还没有得到解释。在同一进程中 的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。

int pthread_mutex_lock(pthread_mutex_t *mutex)

int pthread_mutex_unlock(pthread_mutex_t *mutex)

int pthread_mutex_trylock(pthread_mutex_t *mutex)

pthread_mutex_trylock() 语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回 EBUSY而不是挂起等待。

例如:单例模式下,线程安全的加锁:

class SingleTon

{

public:

static SingleTon* getInstance()

{

pthread_mutex_lock(&mutex);

if(mpSingle == NULL)

{

mpSingleTon = new SingleTon();

}

pthread_mutex_unlock(&mutex);

return mpSingleTon;

}

private:

SingleTon(){};

~SingleTon(){pthread_mutex_desttroy(&mutex,NULL);}

static pthread_mutex_t mutex;

static SingleTon * mpSingleTon;

}

pthread_mutex_t SingleTon::mutex = PTHREAD_MUTEX_INITIALIZER;

SingleTon * SingleTon::mpSingleTon = NULL;

Logo

更多推荐