zoukankan      html  css  js  c++  java
  • linux并发控制之读写信号量

    读写信号量与信号量之间的关系类似于自旋锁与读写自旋锁。
    读写信号量可能会引起进程阻塞,但是它允许N个读执行单元同时访问共享资源,而最多只允许有一个写执行单元访问共享资源;因此,读写信号量是一种相对放宽条件的、粒度稍大于信号量的互斥机制。
    注意:
    信号量不允许任何操作之间有并发。

    理解:
    定义于#include<linux/rwsem.h> 实际上在arch/X86/include/asm/rwsem.h 
    其结构体为:
    struct rw_semaphore {
    long count;
    spinlock_twait_lock;
    struct list_headwait_list;
    #ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_mapdep_map;
    #endif
    };

    其中读锁和写锁函数为:
    static inline void __down_read(struct rw_semaphore *sem)
    {
    asm volatile("# beginning down_read\n\t"
         LOCK_PREFIX _ASM_INC "(%1)\n\t"
         /* adds 0x00000001 */
         "  jns        1f\n"
         "  call call_rwsem_down_read_failed\n"    //跳转到rwsem_down_read_failed函数
         "1:\n\t"                 //给输出信息占位
         "# ending down_read\n\t"
         : "+m" (sem->count)
         : "a" (sem)
         : "memory", "cc");
    }
    static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
    {
    long tmp;
    asm volatile("# beginning down_write\n\t"
         LOCK_PREFIX "  xadd      %1,(%2)\n\t"    //xadd表示原操作数和目的操作数值相交换,而后相加保存入目的操作数
         /* adds 0xffff0001, returns the old value */
         "  test      %1,%1\n\t"            //利用test指令检测count变量来实现
         /* was the count 0 before? */
         "  jz        1f\n"
         "  call call_rwsem_down_write_failed\n"
         "1:\n"
         "# ending down_write"
         : "+m" (sem->count), "=d" (tmp)
         : "a" (sem), "1" (RWSEM_ACTIVE_WRITE_BIAS)
         : "memory", "cc");
    }

    操作:
    struct rw_semaphore rw_sem;                                     //定义读写信号量
    void init_rwsem(struct rw_semaphore* rw_sem);       //初始化读写信号量

    void down_read(struct rw_semaphore* rw_sem);            //获取读信号量
    int down_read_trylock(struct rw_semaphore* rw_sem); //尝试获取读信号量
    void up_read(struct rw_semaphore* rw_sem);             

    void down_write(struct rw_semaphore* rw_sem);           //获取写信号量
    int down_write_trylock(struct rw_semaphore* rw_sem);//尝试获取写信号量
    void up_write(struct rw_semaphore* rw_sem);             

    用例
    rw_semaphore sem;   
    init_rwsem(&sem);   

    down_read(&sem);    
    ...临界区...          
    up_read(&sem);     

    down_write(&sem);   
    ...临界区...             
    up_write(&sem);     

    另:
    void downgrade_write(struct rw_semaphore* sem);
    该函数用于把写者降级为读者,有时,这是必要的。
    因为写者是互斥的、排它的,因此在写者保护读写信号量期间,任何读者或写者都将无法访问该信号量所保护的共享资源,对于那些当前条件下不需要写操作的访问者,降级为写者,将使得等待访问的读者能够立即访问,从而增加了并发性,提高了效率。
  • 相关阅读:
    Windows下载Vim
    分享:分享几个程序员使用的网站
    分享:C语言大礼包(PDF)
    将vscode打造成强大的C/C++ IDE
    最适合做C/C++开发的IDE
    bzoj 2244
    bzoj 1492
    bzoj 3262
    bzoj 1176
    bzoj 2961
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332971.html
Copyright © 2011-2022 走看看