UNIX网络编程-锁(二)

此博客是关于一篇信号量的文章,信号量提供进程间互斥,很方便。用mutex来实现信号量的功能,必须将mutex建立在共享内存上才能实现。所以当需要线程间互斥的时候,最好是用mutex;当用进程间互斥的时候,用sem。归结起来,mutex直接用到进程上,显得无用; sem用到线程上,显得画蛇添足。

1.1 信号量API

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);

创建一个信号量,value值很重要,初始化信号量的为value。

int sem_unlink(const char *name);

依据名字来销毁信号量

sem_t *sem_open(const char *name, int oflag);

打开一个已经存在的信号量

int sem_close(sem_t *sem);

关闭一个信号量,并不是销毁它,依旧存在于内核中,只是从当前进程中卸载。

int sem_wait(sem_t *sem);

sem的值为0,就一直等待;否则就将sem的值-1

int sem_trywait(sem_t *sem);

sem的值为0,就放弃等待,返回值EAGAIN;否则就将sem的值-1

int sem_post(sem_t *sem);

sem的值+1

int sem_getvalue(sem_t *sem, int *

如果返回成功,sval就是sem当前值;否则就获取值出错了

1.2 信号量互斥锁的实现

信号量的互斥锁的类为SemMutex。

1.2.1 成员变量如下:

Sem mutex_; Sem实际上封装了一个sem*指针,初始化为SEM_FAILED

std::string name_; 信号量的名称

1.2.2 实现的成员函数如下:

SemMutex(const char* name);

构造函数初始化Mutex的名称

bool Create();

调用sem_open, 创建信号量, 重要的是信号量的计数初始化为1

bool Destroy();

销毁信号量

bool Open();

打开已经创建的信号量

bool IsOpen();

信号量是否已经打开,实际上判断sem指针是否为SEM_FAILED

bool Lock();

调用sem_wait, 如果信号量的值当前为0,一直等待,表示已经占用了锁资源; 否则sem的值就-1

bool UnLock();

调用sem_post, 释放锁资源,sem的值+1

bool TryLock();

调用sem_trywait, 如果锁资源已经占用,sem的值为0,就不用等待,直接返回EAGAIN。

int LockStatus();

获取锁的状态, -1 ,错误,0 - 加锁状态,1 - 无锁状态;实际上其调用sem_getvalue来获取sem的计数,来查看状态的。 实际上,实现互斥信号量,就是实现一个2值信号量,信号量的值一直在0和1之间变化;1 的时候是无锁状态,不会阻塞;0的时候是加锁状态,就会阻塞。

1.3 信号量读写锁的实现

信号量读写锁的实现,需要一个Sem来记录同时正在read的个数,以及一个SemMutex来实现互斥,其类为RWSem。

其关键就是锁状态的判定了。

p_mutex_->LockStatus == UNLOCK; 表明无锁

p_mutex_->LockStatus == LOCK && p_read_->GetValue() == 0; 已经加了写锁, 即已经加锁,但是读锁的个数为0

p_mutex_->LockStatus == LOCK && p_read_->GetValue() > 0; 已经加了读锁, 即已经加锁,但是读锁的个数>0

1.3.1 RWSem的成员变量:

SemMutex* p_mutex_; 实现读写互斥

Sem* p_read_; 记录当前正在读锁的个数

1.3.2 RWSem的成员函数:

bool Create();

创建p_mutex_和p_read_

bool Destroy();

销毁p_mutex_和p_read_

bool Open();

打开p_mutex_和p_read_

bool Close();

关闭p_mutex_和p_read_

bool WLock();

尝试读锁,当读锁已经占住了资源或者写锁站住资源,就会失败;而不管哪种锁占用了资源,p_mutex_的LockStatus都是锁住状态。 实现机制就是调用p_mutex_的Wait就OK了

bool TryWLock();

尝试读锁,当读锁已经占住了资源或者写锁站住资源,就会失败;而不管哪种锁占用了资源,p_mutex_的LockStatus都是锁住状态。 实现机制就是调用p_mutex_的TryWait就OK了

bool TryRLock();

当写锁占住资源的时候,返回false

当写锁没占住资源并且读锁也没占住资源的时候, p_read_调用Post,读锁的个数+1, 并且调用p_mutex_->Wait(),

当写锁没占住资源并且读锁已经占住资源的时候, p_read_调用Post, 读锁的个数+1, 不用调用p_mutex_->Wait(),否则会阻塞掉的。

bool RLock();

当写锁占住资源的时候,调用p_mutex_->Wait(), 让其阻塞

当写锁没占住资源并且读锁也没占住资源的时候, p_read_调用Post,读锁的个数+1, 并且调用p_mutex_->Wait(), 表示这个锁资源已经被占用

当写锁没占住资源并且读锁已经占住资源的时候, p_read_调用Post, 读锁的个数+1, 不用调用p_mutex_->Wait(),否则会阻塞掉的。

bool UnLock();

当加的锁为读锁的时候,调用p_read_.Post(), 读锁的个数-1,如果读锁的个数减到0,就调用p_mutex_->Post(), 解除锁资源的占用

当加的是写锁的时候, 调用p_mutex_.Post(),

int LockStatus();

0 - 无锁;1- 写锁;2-读锁

 

你可能感兴趣的:(unix)