博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux多线程实践(6) --Posix读写锁解决读者写者问题
阅读量:6980 次
发布时间:2019-06-27

本文共 5486 字,大约阅读时间需要 18 分钟。

Posix读写锁

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,                        const pthread_rwlockattr_t *restrict attr);int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

读写锁与互斥量类似, 不过读写锁允许更高的并行性. 读写锁用于读称为共享锁, 读写锁用于写称为排它锁;

读写锁规则:

  只要没有线程持有给定的读写锁用于写, 那么任意数目的线程可以持有读写锁用于读;

  仅当没有线程持有某个给定的读写锁用于读或用于写时, 才能分配读写锁用于写;

 

Posix自旋锁

int pthread_spin_destroy(pthread_spinlock_t *lock);int pthread_spin_init(pthread_spinlock_t *lock, int pshared);int pthread_spin_lock(pthread_spinlock_t *lock);int pthread_spin_trylock(pthread_spinlock_t *lock);int pthread_spin_unlock(pthread_spinlock_t *lock);

  自旋锁类似于互斥锁, 它的性能比互斥锁更高;

  自旋锁与互斥锁很重要的一个区别在于: 线程在申请自旋锁的时候, 线程并不会挂起, 它总是处于忙等待的状态(一直在自旋, CPU处于空耗的状态);

  自旋锁可用于以下情况:锁被持有的时间短, 而且线程并不希望在重新调度上花费太多的成本.

  自旋锁通常作为底层原语用于实现其他类型的锁: 比如有些互斥锁的实现在试图获取互斥量的时候会自旋一小段时间, 只有在自旋计数到达某一阈值的时候才会休眠; 因此, 很多互斥量的实现非常搞笑, 以至于应用程序采用互斥锁的性能与曾经采用过自旋锁的性能基本上是相同的.

  因此, 自旋锁只在某些特定的情况下有用, 比如在用户层, 自旋锁并不是非常有用, 除非运行在不允许抢占的实时调度类中.

 

读者写者问题

问题描述

  一个数据对象可以为多个并发进程所共享。其中有的进程可能只需要读共享对象的内容,而其他进程可能要更新共享对象的内容。

    读者:只对读感兴趣的进程;

    写者:其他进程(只写,或既读又写);

  规则

    允许多个读者同时读取数据;

    只有一个写者可以写数据;

    写者在写时读者不能读,反之亦然。

/** 实现1: 运用读写锁解决”读者写者问题”解题思路: 将需要读写的文件实现为一个字符串;读者进程: 一次可以将该字符串全部读出, 然后打印读取信息写者进程: 一次只能修改一个字符(该字符从A~Z循环写入), 修改之后打印写入信息**///读写锁pthread_rwlock_t rwlock;const unsigned READERCOUNT = 2; //读者数const unsigned WRITERCONUT = 5; //写者数const int PAPERSIZE = 32;       //文件长度char paper[PAPERSIZE+1];        //文件unsigned short int write_index = 0; //写者需要写入的位置char ch = 'A';  //写者需要写入的字母pthread_t thread[READERCOUNT+WRITERCONUT];  //读者+写者线程//读者线程void *reader(void *args){    int number = *(int *)args;    delete (int *)args;    while (true)    {        //获取共享锁        pthread_rwlock_rdlock(&rwlock);        //开始读        printf("## reader %d was reading...\n", number);        printf("text: %s\n", paper);        printf("   reader %d end reading...\n", number);        //解锁共享锁        pthread_rwlock_unlock(&rwlock);        sleep(1);    }    pthread_exit(NULL);}//写者线程void *writer(void *args){    int number = *(int *)args;    delete (int *)args;    while (true)    {        //获取写锁        pthread_rwlock_wrlock(&rwlock);        //开始写        printf("++ writer %d was writing...\n", number);        paper[write_index] = ch;        write_index = (write_index+1)%PAPERSIZE;        ch = ch+1;        if (ch > 'Z')            ch = 'A';        printf("   writer %d end writing...\n", number);        //释放写锁        pthread_rwlock_unlock(&rwlock);        sleep(1);    }    pthread_exit(NULL);}int main(){    memset(paper, 0, sizeof(paper));    pthread_rwlock_init(&rwlock, NULL);    for (unsigned int i = 0; i < READERCOUNT; ++i)        pthread_create(&thread[i], NULL, reader, new int(i));    for (unsigned int i = 0; i < WRITERCONUT; ++i)        pthread_create(&thread[READERCOUNT+i], NULL, writer, new int(i));    for (unsigned int i = 0; i < READERCOUNT+WRITERCONUT; ++i)        pthread_join(thread[i], NULL);    pthread_rwlock_destroy(&rwlock);}
/** 实现2: 运用Posix信号量使用”读者优先”策略解决”读者写者问题”解题思路:如果新读者到:   ①无读者、写者,新读者可以读;   ②有写者等待,但有其它读者正在读,则新读者也可以读;   ③有写者写,新读者等待。如果新写者到:   ①无读者,新写者可以写;   ②有读者,新写者等待;   ③有其它写者,新写者等待。**/// 需要用两个互斥量实现pthread_mutex_t rmutex;pthread_mutex_t wmutex;const unsigned READERCOUNT = 5; //读者数const unsigned WRITERCONUT = 5; //写者数const int PAPERSIZE = 32;       //文件长度char paper[PAPERSIZE+1];        //文件unsigned short int write_index = 0; //写者需要写入的位置char ch = 'A';  //写者需要写入的字母pthread_t thread[READERCOUNT+WRITERCONUT];  //读者+写者线程int nReader = 0;//读者线程void *reader(void *args){    int number = *(int *)args;    delete (int *)args;    while (true)    {        pthread_mutex_lock(&rmutex);        //如果是第一个读者, 则锁定wmutex        if (nReader == 0)            pthread_mutex_lock(&wmutex);        ++ nReader;        pthread_mutex_unlock(&rmutex);        //开始读        printf("## reader %d was reading...\n", number);        printf("text: %s\n", paper);        printf("   reader %d end reading...\n\n", number);        pthread_mutex_lock(&rmutex);        -- nReader;        //如果是最后一个读者, 则解锁wmutex        if (nReader == 0)            pthread_mutex_unlock(&wmutex);        pthread_mutex_unlock(&rmutex);        sleep(1);    }    pthread_exit(NULL);}//写者线程void *writer(void *args){    int number = *(int *)args;    delete (int *)args;    while (true)    {        //获取写锁        pthread_mutex_lock(&wmutex);        //开始写        printf("++ writer %d was writing...\n", number);        paper[write_index] = ch;        write_index = (write_index+1)%PAPERSIZE;        ch = ch+1;        if (ch > 'Z')            ch = 'A';        printf("   writer %d end writing...\n\n", number);        //释放写锁        pthread_mutex_unlock(&wmutex);        sleep(1);    }    pthread_exit(NULL);}int main(){    memset(paper, 0, sizeof(paper));    pthread_mutex_init(&rmutex, NULL);    pthread_mutex_init(&wmutex, NULL);    for (unsigned int i = 0; i < READERCOUNT; ++i)        pthread_create(&thread[i], NULL, reader, new int(i));    for (unsigned int i = 0; i < WRITERCONUT; ++i)        pthread_create(&thread[READERCOUNT+i], NULL, writer, new int(i));    for (unsigned int i = 0; i < READERCOUNT+WRITERCONUT; ++i)        pthread_join(thread[i], NULL);    pthread_mutex_destroy(&rmutex);    pthread_mutex_destroy(&wmutex);}

  “读者优先”思想小结: 读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。该算法只要还有一个读者在活动,就允许后续的读者进来,该策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。而写者就始终被挂起,直到没有读者为止.

转载地址:http://gcnpl.baihongyu.com/

你可能感兴趣的文章
JAVA-基础(Class对象及反射)
查看>>
一个疯狂想法
查看>>
c# 关闭软件 进程 杀死进程
查看>>
swift集成alamofire的简单封装
查看>>
javascript模块化、模块加载器初探
查看>>
PL/SQL Developer远程访问Oracle数据库
查看>>
我的友情链接
查看>>
eclipse插件安装方法
查看>>
Javascript中的字符串链接和Array.join()方法时间效率对比
查看>>
为什么用Immutable.js代替普通js对象?
查看>>
Ossim系统常见测试方法
查看>>
创业那些年,我们一起走过的坑
查看>>
Oracle软件的美学变迁
查看>>
HttpServlet中getAllDeclaredMethods()方法
查看>>
面试题2:二维数组中的查找
查看>>
文件上传的渐进式增强
查看>>
leetcode -- Sort Colors
查看>>
C#中使用自定义的纸张大小
查看>>
1z0-052 q209_3
查看>>
行测题哦
查看>>