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-读锁

     
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/wind-qu/p/3724055.html
Copyright © 2011-2022 走看看