Quantcast
Channel: Sam的技术Blog
Viewing all articles
Browse latest Browse all 158

Linux线程间同步

$
0
0
作者: Sam (甄峰)  sam_code@hotmail.com

Linux下线程间同步,之前只用到mutex.  这次把互斥锁(mutex),条件变量(cond)和读写锁(rwlock)都记录下来。

1. 互斥锁(mutex):
互斥锁的基本想法是: 某个Thread 把mutex锁住后,其它Thread(或本Thread) 再调用lock时,会被告知已经锁住。直到mutex被unlock.
它的主要作用是: 同一时刻,只允许一个Thread执行一个关键部分的代码。

1.1: 初始化和销毁:
在使用mutex 之前,需要初始化它。不再使用时,需要销毁它。
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

1.1.1: 初始化:
方法一 动态初始化:
pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr)
将要初始化参数一所指向mutex object.  
参数二指向attr是这个mutex object的特性。可以为NULL,此时mutex attribute使用缺省设置。
当pthread_mutex_init()执行成功时,mutex object是初始化过的,同时也是unlock的。
未定义的行为:
A. 只有互斥体本身(mutex object)可以用来执行同步操作。 pthread_mutex_lock(), pthread_mutex_trylock(), pthread_mutex_unlock(), pthread_mutex_destroy()使用mutex object 的拷贝的行为,都是未定义的。隐含着危险。
B. 尝试初始化已经初始化过的mutex object 是未定义行为
顺利完成,则返回0. 否则,返回error号。


方法二 静态初始化: 
pthread_mutex_t mutex_read = PTHREAD_MUTEX_INITIALIZER;
与pthread_mutex_init(&mutex_read, NULL)作用完全相同。


1.1.2: 销毁
pthread_mutex_destroy(pthread_mutex_t *mutex)
它将销毁参数所指向的mutex object.
一个被销毁的mutex object可以被重新初始化。
pthread_mutex_destroy()可以安全的销毁unlock的mutex object. 销毁未unlock的mutex会导致未知结果。
顺利完成,则返回0. 否则,返回error号。


1.2:加锁:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);

1.2.1:pthread_mutex_lock():
调用pthread_mutex_lock()去锁一个mutex object, 则这个mutex object 会被锁住, 函数会返回 0或者[EOWNERDEAD].  
如果这个mutex object已经被其它Thread 锁住。 则当前调用pthread_mutex_lock()的Thread被阻塞,直到mutex object变得可用(unlock). 这就保证了在另一个Thread unlock之前。 此Thread无法执行下面的指定代码。


1.2.1:pthread_mutex_trylock():
其它与pthread_mutex_lock()类似。唯一区别在于:
当mutex object已经被锁住时, 它不是被阻塞,而是立刻返回(EBUSY =16)。



1.3:解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
释放Mutex Object. 它变成unlock状态。此时,如果有Thread被这个mutex阻塞,scheduling policy将会检查有多少个Thread被阻塞,它会挑选一个解除阻塞。



2. 条件变量(Cond): 
条件变量是利用线程间共享全局变量进行同步的一种机制.
某个Thread使用Cond,阻塞Thread, 来等待某个触发条件的发生。
另一个Thread触发之。

2.1: 初始化和销毁
2.1.1: 初始化Cond:
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
参数二: Linux 未能实现,所以为NULL。使用缺省设置。

2.1.2:销毁Cond:
int pthread_cond_destroy(pthread_cond_t *cond);
只有在没Thread等待的情况下,才可以销毁这个cond。


2.2: 等待触发函数
2.2.1: 无限时等待:
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
这个等待函数需要和mutex配合使用。
先讲解它本身:
在执行pthread_cond_wait()时,它会做两件事:
1. 首先把参数二中指定的Mutex Object 自动unlock。
2. 阻塞住Thread. 等待条件变量(cond)被触发。


当条件变量真被触发时, pthread_cond_wait()在返回之前,会把参数二中指定的Mutex Object 自动 lock住。

在调用pthread_cond_wait()前,需要使用pthread_mutex_lock()锁住参数二所指向的Mutex Object.
在调用pthread_cond_wait()后,需要使用pthread_mutex_unlock()解开参数二所指向的Mutex Object.

用法如下:
pthread_mutex_lock(&mutex);
  1. pthread_cond_wait(&cond,&mutex);
  2. pthread_mutex_unlock(&mutex);



2.2.2: 限时等待:
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
除了增加time外,其它与pthread_cond_wait()相同。



2.3:激活触发:
2.3.1: 激活一个等待该条件的线程(存在多个等待线程时按入队顺序激活其中一个)
int pthread_cond_signal(pthread_cond_t *cond);

2.3.2:激活所有等待线程
int pthread_cond_broadcast(pthread_cond_t *cond);




3. 读写锁:
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
 
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);





 

Viewing all articles
Browse latest Browse all 158

Trending Articles