当前位置:早雪网网络学院编程文档C/C++ → Solaris2.4 多线程编程指南3--使用同步对象编程

Solaris2.4 多线程编程指南3--使用同步对象编程

减小字体 增大字体 作者:不详  来源:supcode.com收集整理  发布时间:2005-7-22 19:39:47
个可用的位置里。
同时,消费者线程也许正在等待有信息放入缓冲区。这些线程等待条件变量more。 一个生产者线程,在刚刚把信息放入存储区后,调用cond_signal()来唤醒下一个等 待的消费者。(如果没有等待的消费者,这个调用无效。)最后,生产者线程释放互 斥锁,允许其他线程操作缓冲区。

Code Example 3-12 生产者/消费者问题--生产者
Void producer(buffer_t *b, char item) {
Mutex_lock(&b->mutex);

While ( b->occupied >= BSIZE)
Cond_wait(&b->less, &b->mutex);
Assert(b->occupied < BSIZE);
b->buf(b->nextin++)=item;
b->nextin %=BSIZE;
b->occupied ++;
/* now: either b->occupied < BSIZE and b->nextin is the index
of the next empty slot in the buffer, or
b->occupied == BSIZE and b->nextin is the index of the
next (occupied) slot that will be emptied by a consumer
(such as b-> == b->nextout) */

cond_signal(&b->more);
mutex_unlock(&b->mutex);
}
注意assert()命令的用法;除非代码用NDEBUG方式编译,assert()在参数为真时 (非零值)不做任何操作,如果参数为假(参数为假),程序退出。
这种声明在多线程编程中特别有用--在失败时它们会立刻指出运行时的问题, 它们还有其他有用的特性。
后面说明代码可以更加称得上是声明,但它太过复杂,无法用布尔表达式来表达,所以用文字来写。???
声明和说明???都是不变量的实例。它们都是一些逻辑命题,在程序正常执行时不应当被证伪,除非一个线程试图改变非变量说明段的变量。???
不变量是一种极为有用的技术。即使它们没有在程序中写出,在分析程序中也需要把它们看成不变量。
生产者代码中的不变量(说明部分)在程序执行到这一段时一定为真。如果你把这段说明移到mutex_unlock()后面,它将不一定保持为真。如果将其移到紧跟着声明的后面,它仍然为真。
关键在于,不变量表现了一个始终为真的属性,除非一个生产者或一个消费者正 在改变缓冲区的状态。如果一个线程正在操作缓冲区(在互斥锁的保护下),它将暂 时将不变量置为假。但是,一旦线程结束对缓冲区的操作,不变量会立刻恢复为真。
示例3-13为消费者的代码。它的流程和生产者是对称的。
Code Example 3-13 生产者/消费者问题--消费者
Char consumer(buffer_t *b){
Char item;
Mutex_lock(&b->mutex);
While(b->occupied <=0)
Cond_wait(&b->more, &b->mutex);
Assert(b->occupied>0);
Item=b->buf(b->nextout++);
b->nextout %=BSIZE;
b->occupied--;
/* now: either b->occupied>0 and b->nextout is the index of
the nexto ccupied slot in the buffer, or b->occupied==0
and b->nextout is the index of the next(empty) slot that
will be filled by a producer (such as b->nextout ==b->nextin) */
cond_signal(&b->less);
mutex_unlock(&b->mutex);
return(item);
}

3.3多读单写锁

读写锁允许多个线程同时进行读操作,但一个时间至多只有一个线程进行写操作。
表3-3 读写锁的函数
函数 操作
rwlock_init(3T) 初始化一个读写锁
rw_rdlock(3T) 获得一个读锁
rw_tryrdlock(3T) 试图获得一个读锁
rw_wrlock(3T) 获得一个写锁
rw_trywrlock(3T) 试图获得一个写锁
rw_unlock(3T) 使一个读写锁退出阻塞
rwlock_destroy(3T) 清除读写锁状态
如果任何线程拥有一个读锁,其他线程也可以拥有读锁,但必须等待写锁。如 果一个线程拥有写锁,或者正在等待获得写锁,其它线程必须等待获得读锁或写锁。
读写锁比互斥锁要慢,但是在所保护的数据被频繁地读但并不频繁写的时候可以提高效率。
如果两个进程有共享的可读写的内存,可以在初始化时设置成用读写锁进行进程间的线程同步。
读写锁使用前一定要初始化。

3.3.1初始化一个读写锁
rwlock_init(3T)
#include (or #include )
int rwlock_init(rwlock_t *rwlp, int type, void * arg);
用rwlock_init()来初始化由rwlp指向的读写锁并且设置锁的状态为没有锁。
Type可以是如下值之一(arg现在先不谈)。
USYNC_PROCESS 读写锁可以实现进程间的线程同步。
USYNC_THREAD 读写锁只能在进程内部实现线程同步。
多线程不能同时初始化一个读写锁。读写锁可以通过分配零内存来初始化,在这种情况下,一定要设置USYNC_THREAD。一个读写锁在使用当中不能被其他线程重新初始化。
返回值--rwlock_init()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL 非法参数。
EFAULT rwlp或arg指向一个非法地址。

3.3.2获得一个读锁

rw_rdlock(3T)
#include (or #include )
int rw_rdlock(rwlock_t *rwlp);
用rw_rdlock()来给一个由rwlp指向的读写锁加上读锁。如果读写锁已经被加写锁,则调用线程阻塞直到写锁被释放。否则,读锁将被成功获得。
返回值--rw_rdlock()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL 非法参数。
EFAULT rwlp指向一个非法地址。

3.3.3试图获得一个读锁

rw_tryrdlock(3T)
#include (or #include )
int rw_tryrdlock(rwlock_t *rwlp);
试图给读写锁加读锁,如果读写锁已经被加写锁,则返回错误,而不再进入阻塞状态。否则,读锁将被成功获得。
返回值--rw_tryrdlock ()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL 非法参数。
EFAULT rwlp指向一个非法地址。
EBUSY 由rwlp指向的读写锁已经被加写锁。

3.3.4获得一个写锁

rw_wrlock(3T)
#include (or #include )
int rw_wrlock(rwlock_t *rwlp);
用rw_wrlock()为由rwlp指向的读写锁加写锁。如果该读写锁已经被加读锁或写锁,则调用线程阻塞,直到所有锁被释放。一个时刻只有一个线程可以获得写锁。
返回值--rw_wrlock ()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返回相关值。
EINVAL 非法参数。
EFAULT rwlp指向一个非法地址。

3.3.5试图获得写锁

rw_trywrlock(3T)
#include (or #include )
int rw_trywrlock(rwlock_t *rwlp);
用rw_trywrlock()试图获得写锁,如果该读写锁已经被加读锁或写锁,它将返回错误。
返回值--rw_trywrlock ()在成功执行后返回零。其他值意味着错误。在以下情况发生时,函数失败并返

上一页  [1] [2] [3] [4] [5] [6]  下一页

[数据载入中...] [返回上一页] [打 印]