当前位置:   article > 正文

详细教程 - 进阶版 鸿蒙harmonyOS应用 第十七节——鸿蒙OS多线程编程指南_鸿蒙 多线程

鸿蒙 多线程

1. 概述

        线程是操作系统调度的最小单元,鸿蒙OS使用轻量级线程实现了良好的并发性能。

        相比进程间的切换,线程间切换成本更低,可以有效利用多核CPU。但直接使用线程也会增加编程复杂度。

        本文将详细介绍鸿蒙OS的多线程编程模型、线程间通信与同步机制、并发安全、最佳实践等内容。

2. 线程创建

我们首先来看下鸿蒙OS线程的两种典型创建方式。

2.1 通过函数创建

这是最简单直观的线程定义方式,你只需要实现一个线程函数即可:

  1. void DownloadFile() {
  2. // 1. 获取网络资源
  3. // 2. 存储文件
  4. // 3. 更新进度
  5. }
  6. OHOS::NativeThread thread(DownloadFile);

这样就创建了一个执行下载任务的工作线程,非常轻量简洁。

2.2 通过继承类创建

如果需要复用线程逻辑,可以使用C++面向对象的方式定义线程类:

  1. class DownloadWorker : public OHOS::NativeThread {
  2. void Run() override {
  3. // 下载文件逻辑
  4. }
  5. };
  6. // 创建线程对象执行下载任务
  7. DownloadWorker worker;
  8. worker.Start();

这样也屏蔽了接口细节,也更符合面向对象的设计思想。

3. 线程间通信

线程间最基本的通信方式就是共享内存区。但为了协调操作顺序,需要一些同步原语。

3.1 互斥量

互斥量用于排他性地保护共享资源:

  1. std::mutex mutex;
  2. // 线程1:
  3. mutex.lock();
  4. // 访问共享内存
  5. mutex.unlock();
  6. // 线程2:
  7. mutex.lock();
  8. // 访问共享内存
  9. mutex.unlock();

很好地解决了同时访问的问题。

3.2 条件变量

条件变量可以实现线程间的同步等待与唤醒。

  1. std::condition_variable cv;
  2. std::mutex mutex;
  3. // 线程1等待条件
  4. unique_lock<mutex> lock(mutex);
  5. cv.wait(lock, []{return ready;});
  6. // 线程2准备好后激发条件
  7. lock.lock()
  8. ready = true;
  9. cv.notify_one();

这种机制可以协调多个线程的工作顺序。

3.3 信号量

信号量为线程同步提供了更灵活的选项:

  1. std::counting_semaphore sem(3); //设置资源数为3
  2. // 线程1/2/3可以立即获取 1个资源
  3. sem.acquire();
  4. // 线程4被阻塞等待
  5. sem.acquire();
  6. // 释放资源,信号量值加1
  7. sem.release();

根据资源数量进行同步,十分实用。

4. 内存访问与竞争

        多线程环境下共享内存的访问顺序是不确定的。如果多个线程同时修改数据,将引发数据竞争和错误结果。

例如下面代码中的计数逻辑就存在问题:

  1. // 共享内存中的全局计数变量
  2. int g_count = 0;
  3. // 多个线程同时执行
  4. void Increment() {
  5. g_count++;
  6. }

这就需要使用前面介绍的互斥机制来正确同步内存访问。

5. 线程安全集合

针对共享内存中容器类的并发访问,鸿蒙提供了线程安全的容器实现。

5.1 mutex保护

可以使用mutex保护下的集合:

  1. std::mutex mutex;
  2. std::vector<int> buffer;
  3. // 线程安全写入
  4. mutex.lock();
  5. buffer.push_back(1);
  6. mutex.unlock();
  7. // 线程安全读取
  8. int v = 0;
  9. mutex.lock();
  10. v = buffer[0];
  11. mutex.unlock();

这种锁的粒度比较粗,影响了并发性。

5.2 并发集合

更好的选择是采用CONCURRENT集合:

  1. // 线程安全动态数组
  2. OHOS::ConcurrentVector<int> buffer;
  3. // 高效并发插入
  4. buffer.PushBack(1);
  5. // 高效并发访问
  6. int v = buffer[0];

这种细粒度锁控制可以实现很好的并发吞吐量。

6. 并发设计模式

除上述基本的同步机制外,利用一些并发设计模式也能简化线程间协作:

  • Future: 实现了异步数据同步
  • 工作线程池:管理了重复任务
  • 生产者消费者:利用缓冲区解耦生产和消费等

合理应用设计模式是构建高效可靠的多线程程序的基础。

7. 最佳实践

综合上述内容,在鸿蒙OS多线程编程过程中,还需要注意如下最佳实践:

  • 最小化共享内存区,减少竞争点
  • 多使用无锁并发数据结构
  • 避免锁的嵌套,软死锁风险
  • 分解逻辑,减少临界区代码量
  • 分离计算密集型和I/O密集型任务
  • 利用并行算法,分而治之
  • 监控死锁和线程泄漏情况

合理应用这些建议,能获得更好的并发性能。

8. 总结

        本文主要介绍了鸿蒙OS的多线程创建与同步互斥机制,解释了线程不安全的根本原因,并给出了设计实现线程安全的各种方式,最后提出了并发优化的最佳实践。

        多线程并发大大提高了程序执行效率,但也增加了编程难度。希望通过阅读本指南,可以更好地管理和避免线程风险,构建高性能的鸿蒙OS应用程序。

        有不对的地方,欢迎大家评论区批评指正

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号