• 多线程、多进程同时操作MMAP,会怎么样?


    今天我们来聊聊同步,假设一种场景,就是在客户端Activity中,开启多个线程同时写入mmap内存中,看看会怎样

    多线程写入

    1. private fun testMultiThreadWriteMMIPC() {
    2. "set data".print(getProcessName())
    3. val countDownLatch = CountDownLatch(2)
    4. Thread {
    5. var index = 10000
    6. //重复写入一万次
    7. repeat(10000) {
    8. index++
    9. MMIPC.setData(index.toString(), index.toString())
    10. }
    11. countDownLatch.countDown()
    12. }.start()
    13. Thread {
    14. var index = 20000
    15. //重复写入一万次
    16. repeat(10000) {
    17. index++
    18. MMIPC.setData(index.toString(), index.toString())
    19. }
    20. countDownLatch.countDown()
    21. }.start()
    22. //等待两个线程结束
    23. countDownLatch.await()
    24. //打印写入数据的长度
    25. MMIPC.getData("").length.toString().print(getProcessName())
    26. }

    输出日志

    1. 2022-07-20 22:20:46.743 9933-9933/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: init
    2. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc D/MMIPC->: open file /data/user/0/com.zzy.mmipc/files
    3. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc E/MMIPC->: pid[9933]
    4. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc D/MMIPC->: open m_fd[78], /data/user/0/com.zzy.mmipc/files/default_mmap.ipc
    5. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc D/MMIPC->: m_fd size[0]
    6. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc D/MMIPC->: getFileSize m_file_size 0, default_mmap_size 4161536
    7. 2022-07-20 22:20:46.744 9933-9933/com.zzy.mmipc D/MMIPC->: mmap success
    8. 2022-07-20 22:20:46.845 9933-9933/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: set data
    9. 2022-07-20 22:20:46.913 9933-9933/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: 237004

    正常长度等于20000*12 = 240000,因为setData,我会将key和value进行预处理变成如下,所以一次setData的长度是12,那么重试两万次就是 24万

    string content = key + ":" + value + ",";

    有什么办法可以解决该问题呢,往下看

    HandlerThread

    利用Looper机制,实现单线程中让所有的任务按顺序执行,直接代码验证效果,创建一个dev-looper分支,然后代码改变如下

    ​然后测试结果如下,这次是240000

    1. 2022-07-20 22:43:47.874 11336-11336/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: init
    2. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc D/MMIPC->: open file /data/user/0/com.zzy.mmipc/files
    3. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc E/MMIPC->: pid[11336]
    4. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc D/MMIPC->: open m_fd[76], /data/user/0/com.zzy.mmipc/files/default_mmap.ipc
    5. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc D/MMIPC->: m_fd size[0]
    6. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc D/MMIPC->: getFileSize m_file_size 0, default_mmap_size 4161536
    7. 2022-07-20 22:43:47.897 11336-11336/com.zzy.mmipc D/MMIPC->: mmap success
    8. 2022-07-20 22:43:48.265 11336-11336/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: set data
    9. 2022-07-20 22:43:56.241 11336-11336/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: 240000

    我们想想,这样实现有什么问题,功能没什么问题,但失去了原本用C++实现的好处,那就是跨平台能力,如果再IOS端,我们如何实现呢?接下来我们考虑用C++的方式实现对多线程写入

    C/C++Linux服务器开发高级架构师/C++后台开发架构师​免费学习地址

    【文章福利】另外还整理一些C++后台开发架构师 相关学习资料,面试题,教学视频,以及学习路线图,免费分享有需要的可以自行添加:Q群:720209036 点击加入~ 群文件共享

    互斥锁(mutex)

    该锁限制同一时间只有一个线程访问数据,实现如下,下面跨进程的时候在详细了解mutex

    1. //声明
    2. pthread_mutex_t m_lock;
    3. //setData函数中使用
    4. void MMIPC::setData(const string &key, const string &value) {
    5. //加锁
    6. pthread_mutex_lock(&m_lock);
    7. string content = key + ":" + value + ",";
    8. // ALOGD("setData content=%s", content.c_str());
    9. size_t numberOfBytes = content.length();
    10. if (m_position + numberOfBytes > m_file_size) {
    11. auto msg = "m_position: " + to_string(m_position) + ", numberOfBytes: " +
    12. to_string(numberOfBytes) +
    13. ", m_file_size: " + to_string(m_file_size);
    14. throw out_of_range(msg);
    15. }
    16. m_position = strlen(m_ptr);
    17. memcpy(m_ptr + m_position, (void *) content.c_str(), numberOfBytes);
    18. // ALOGD("setData success m_ptr.len=%d", m_position + numberOfBytes);
    19. //释放锁
    20. pthread_mutex_unlock(&m_lock);
    21. }

    测试日志

    1. 2022-07-20 23:04:10.958 12322-12322/com.zzy.mmipc D/MMIPC->: 进程:com.zzy.mmipc 日志: init
    2. 2022-07-20 23:04:10.959 12322-12322/com.zzy.mmipc D/MMIPC->: open file /data/user/0/com.zzy.mmipc/files
    3. 2022-07-20 23:04:10.959 12322-12322/com.zzy.mmipc E/MMIPC->: pid[12322]
    4. 2022-07-20 23:04:10.959 12322-12322/com.zzy.mmipc D/MMIPC->: open m_fd[78], /data/user/0/com.zzy.mmipc/files/default_mmap.ipc
    5. 2022-07-20 23:04:10.959 12322-12322/com.zzy.mmipc D/MMIPC->: m_fd size[0]
    6. 2022-07-20 23:04:10.959 12322-12322/com.zzy.mmipc D/MMIPC->: getFileSize m_file_size 0, default_mmap_size 4161536
    7. 2022-07-20 23:04:10.959 1
  • 相关阅读:
    1768.交替合并字符串
    Apache服务Rwrite功能使用
    高通导航器软件开发包使用指南(16)
    常用数据库的最大并发和实际并发
    Go vs Java vs C# 语法对比
    一文讲解Vuex实现原理
    vue2 过渡到 vue3 指南
    物理层物理层
    DispatcherServlet工作原理简介说明
    【附源码】计算机毕业设计SSM网上销售系统
  • 原文地址:https://blog.csdn.net/Linuxhus/article/details/127571471