zoukankan      html  css  js  c++  java
  • 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-读锁

     
  • 相关阅读:
    JAVAOO 11 12 15 13 章
    JAVAOO 继承~接口 笔记
    JAVAOO 5~6章笔记
    JAVAOO 1—4章学习重点
    CSS超链接和导航
    XHTML基础
    ZooKeeper伪集群安装配置
    异常,常用类,集合
    继承,抽象,多态,接口
    java oo 第一周
  • 原文地址:https://www.cnblogs.com/wind-qu/p/3724055.html
Copyright © 2011-2022 走看看