几个线程共同访问一块内存,这块内存分为10个部分,简单的方法是10个mutex,更好方法?

registercsdn 2017-12-22 02:00:36
有2个线程,写线程 和 读线程,它们共同访问同一块内存,这块内存分为10个小部分,比如mem[0], mem[1], 。。。mem[9].
读线程 和 写线程不能同时访问同一个小部分

最简单的方法是10个mutex来分别保护10个小部分。

有没有方法用1个mutex来保护?

请提供一个举例程序或链接,谢谢大家
...全文
791 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
mstlq 2018-03-08
  • 打赏
  • 举报
回复
给个例子楼主吧,思路就是我10楼所说的,楼主顺便还可以体会一下unique_lock和condition_variable的使用

#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#define THREAD_COUNT_FOR_TEST 10
using namespace std;

int volatile g_mems[THREAD_COUNT_FOR_TEST]; //简化一下, 用mems[0]~~mems[THREAD_COUNT_FOR_TEST-1]用这个来代表10个不同内存区域
bool volatile g_memsLockFlag[THREAD_COUNT_FOR_TEST];//标记内存是否已被占
std::mutex gl_mutex;
std::condition_variable g_cv;
void  readTread(int memIdx, int randSeed)
{
    srand(randSeed);
    //本代码中所有sleep都是为了模拟线程卡顿,验证互斥保护的效果
    int sleepTime = rand() % 1500 ;
    std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
    printf("read thread, idx(%d), after %d ms sleep, begin to work!\n", memIdx, sleepTime);
    {
        std::unique_lock<std::mutex> lock(gl_mutex);
        g_cv.wait(lock, [memIdx](){return !g_memsLockFlag[memIdx]; });
        g_memsLockFlag[memIdx] = true;
    }
    //模拟读数据,这里是简单打印
    printf("read thread, idx(%d), get value:%d!\n", memIdx, g_mems[memIdx]);
    {
        std::unique_lock<std::mutex> lock(gl_mutex);
        g_memsLockFlag[memIdx] = false;
    }
    printf("read thread, idx(%d), finished work and unlock source!\n", memIdx);
    g_cv.notify_all();
}

void  wirteTread(int memIdx, int randSeed)
{
    srand(randSeed);
    //本代码中所有sleep都是为了模拟线程卡顿,验证互斥保护的效果
    int sleepTime = rand() % 1500;
    std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
    printf("write thread, idx(%d), after %d ms sleep, begin to work!\n", memIdx, sleepTime);
    {
        std::unique_lock<std::mutex> lock(gl_mutex);
        g_cv.wait(lock, [memIdx](){return !g_memsLockFlag[memIdx]; });
        g_memsLockFlag[memIdx] = true;
    }
    int newValue =1 + rand() % 100;
    g_mems[memIdx] = newValue; //模拟写数据,这里是简单赋值
    printf("write thread, idx(%d), set value to %d!\n", memIdx, g_mems[memIdx]);
    
    sleepTime = rand() % 1500;
    std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
    printf("write thread, idx(%d), after %d ms sleep, continue to work!\n", memIdx, sleepTime);

    int oldValue = g_mems[memIdx];
    g_mems[memIdx]++; //模拟写数据,这里是简单自增
    printf("write thread, idx(%d),set new value to %d,the old value (%d) will not read by other thread, because we has not unlock source yet!\n", memIdx, g_mems[memIdx], oldValue);
    {
        std::unique_lock<std::mutex> lock(gl_mutex);
        g_memsLockFlag[memIdx] = false;
    }
    printf("write thread, idx(%d), finished work and unlock source!\n", memIdx);
    g_cv.notify_all();
}



int main()
{
    srand(time(NULL));
    std::thread rt[THREAD_COUNT_FOR_TEST];
    std::thread wt[THREAD_COUNT_FOR_TEST];
    for (int i = 0; i < THREAD_COUNT_FOR_TEST; ++i)
    {
        wt[i] = std::thread(wirteTread, i,rand());
        rt[i] = std::thread(readTread, i, rand());
    }
    for (int i = 0; i < THREAD_COUNT_FOR_TEST; ++i)
    {
        wt[i].join();
        rt[i].join();
    }
    return 0;
}
我看你有戏 2018-01-02
  • 打赏
  • 举报
回复
开一个线程专门处理这块内存数据,其他线程把数据POST过来
sky065530 2018-01-02
  • 打赏
  • 举报
回复
把内存读写当作I/O操作,用Windows的I/O完成端口应该可以解决。
mstlq 2018-01-01
  • 打赏
  • 举报
回复
可以一个mutex解决,关键是只锁标记内存是否被使用中的flag,不锁读写操作自身。。 如果明天不用陪老婆逛街的话,可以给楼主写个例程。。。
firerun 2017-12-29
  • 打赏
  • 举报
回复
干嘛要锁?每块内存弄一个标志位就ok了。内存被读或者被写时,置位相应标志位,谁设置的标志位谁负责复位。你再在线程内对遇到不能操作的内存快时进行相应的处理。 这样程序不会阻塞。 不过根据你的需求逻辑,我觉得你的更适用信号量。设置2个10个资源的信号量,信号量sema1用于释放已写资源,初始态为0,信号量sem2用于释放已读资源,初始态为10。写线程写内存时,先请求sem2,写完后释放一个sem1。读线程获取到sem1的资源才能读,读完了就释放一个sem2,你是一个线程读一个线程写,所以你肯定是按顺序循环进行。如果你是多个写或者多个读,那这时是无序的,那你就要想办法搞明白每块内存的状态,是空闲的?是已写的?读写线程分别对相应状态的内存进行操作。
ztenv 版主 2017-12-27
  • 打赏
  • 举报
回复
更好的方法:无锁化
Qlaiaqu 2017-12-25
  • 打赏
  • 举报
回复
引用 4 楼 registercsdn 的回复:
[quote=引用 1 楼 paschen 的回复:] 控制几块内存,就需要几个MUTEX
我是楼主。 如果用10个mutex的话,大概这么写。 3个函数,一个读线程,一个写线程,一个检查内存小块的函数。 读的时候,先在检查内存小块函数的里面lock, 读完后,在读线程函数中unlock。 同样原理 写线程。 请大家提供一个举例程序或者程序链接,我研究一下,看看有没有更好的写法。[/quote] 你评估一下具体应用,如果锁住的数据操作花费时间不长,用一个锁保护所有内存即可,对于一个内存一个锁,复杂度高了容易想不清楚。
heronism 2017-12-25
  • 打赏
  • 举报
回复
引用 1 楼 paschen 的回复:
控制几块内存,就需要几个MUTEX
同意。
自信男孩 2017-12-22
  • 打赏
  • 举报
回复
个人建议用一个锁即可,这个锁是锁住这个共享的内存(所有小块);
registercsdn 2017-12-22
  • 打赏
  • 举报
回复
引用 1 楼 paschen 的回复:
控制几块内存,就需要几个MUTEX
我是楼主。 如果用10个mutex的话,大概这么写。 3个函数,一个读线程,一个写线程,一个检查内存小块的函数。 读的时候,先在检查内存小块函数的里面lock, 读完后,在读线程函数中unlock。 同样原理 写线程。 请大家提供一个举例程序或者程序链接,我研究一下,看看有没有更好的写法。
registercsdn 2017-12-22
  • 打赏
  • 举报
回复
引用 2 楼 fengxuxing 的回复:
一个读写锁保护整块内存不就行了,如果每个小内存部分需要并行访问,那就每个小内存一个锁了,但是如果遇到访问了第一个小内存又有访问其它小内存的需求,就需要考虑死锁的问题了。
比如 我在写线程在写第5个小块的时候,允许读线程访问其他所有小块,假如需要读第五个,就要等写线程写完之后再读取。 同样假如某块正在读,只可以写在其他小块,只有当前小块读完之后,才可以写入当前小块。 这样必须用10个mutex吗?
Qlaiaqu 2017-12-22
  • 打赏
  • 举报
回复
一个读写锁保护整块内存不就行了,如果每个小内存部分需要并行访问,那就每个小内存一个锁了,但是如果遇到访问了第一个小内存又有访问其它小内存的需求,就需要考虑死锁的问题了。
paschen 版主 2017-12-22
  • 打赏
  • 举报
回复
控制几块内存,就需要几个MUTEX
#### 收益: 学习《optee系统开发精讲 》套餐的收益如下:1、全体系的掌握optee的核心知识点(多核多线程、启动流程、各类API、TA/PTA/STA、driver、service、各类设计思想、内存管理、中断管理...);2、掌握TEE OS的设计核心思想(不限与optee,对其它TEE也是如此),能够进入软件架构层次的各项设计;3、快速熟悉大系统软件的各项组件,能够进行大系统软件之间的设计或排查问题4、学习和理解理解Armv8/Armv9架构、Trustzone架构5、技术水平提升N个level, 掌握快速的学习方法;#### 课程简介和大纲 该课程包含但不限与以下章节:optee的组件介绍optee os启动流程optee os的初始化流程optee os线程向量表及其作用进入optee os的八种方式optee os的异常向量表和设计模型optee os对irq中断的处理optee os对fiq中断的处理optee os的内存管理optee os的MMU的使用optee os的根密钥(信任根)optee os的RPC机制optee os的存储系统optee os的SFS系统optee os的RPMB机制的实现optee os的Timer实现optee os中实现的GP APIoptee os中的系统调度optee os中密码学函数的支持optee os中的线程调度CA/TA的开发模型optee os中的serviceoptee os中的 PTAoptee os中的 secure driveroptee os中的 Early TAoptee中spinlock的实现原理详解optee中mutex的实现方式optee的栈指针和栈内存的介绍optee中使用虚函数(平台客制化)的设计模型共享内存的介绍optee os的标准错误码TA的签名和验签TA链接静态库的方法

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧