HarmonyOS鸿蒙Next开发过程中有没有遇到锁的问题?

HarmonyOS鸿蒙Next开发过程中有没有遇到锁的问题? 新手想要了解一下开发过程中比较常见锁的问题,该如何避免呢?求大佬指点

7 回复

楼主,例如在taskPool中搭配异步锁实现多线程中任意一次请求接口成功后,其余线程不再请求接口。

以下是问题的描述以及解决方案:

【问题现象】

ArkTS并发编程时,会多次请求同一接口,目前希望能使用taskPool搭配异步锁实现并发请求时接口成功被调用一次后可以不重复调用接口:例如多个线程任务同时执行A方法,执行完A方法后都请求B接口。期望只要有一个线程任务请求B接口成功后其他的线程执行完A就结束,不再继续请求B接口。

【背景知识】

  • taskPool为应用程序提供多线程环境,降低资源消耗、提高系统性能,无需管理线程生命周期。
  • AsyncLock是一种专为异步编程设计的同步机制,主要用于解决异步环境下的资源竞争和并发控制问题。为了解决多线程并发任务间的数据竞争问题,ArkTS引入了异步锁能力。异步锁可能会被类对象持有,因此为了更方便地在并发实例间获取同一个异步锁对象,AsyncLock对象支持跨线程引用传递。

【解决方案】

  1. 实现了一个HarmonyOS ArkTS环境下的全局状态管理类,声明异步锁并编写异步操作:
import { ArkTSUtils } from '@kit.ArkTS';

"use shared" // 指令声明模块为进程内共享单例

@Sendable
// 通过@Sendable装饰器确保类实例可跨线程安全传输
class GlobalState {
  private status: number = 1 // 1-状态正常  0-状态不正常
  public readonly MAX_RETRY_TIME: number = 3
  public retryTime: number = 0

  constructor() {

  }

  setState(status: number) {
    this.status = status
  }

  isConnected() {
    return this.status === 1
  }

  // 采用AsyncLock实现异步操作的互斥访问
  lock_: ArkTSUtils.locks.AsyncLock = new ArkTSUtils.locks.AsyncLock();

  public setLock(): string {
    // 对需要保护的数据加异步锁,使用异步锁保护临界区
    console.info('当前state1:' + this.status)
    if (!this.status) {
      console.info('处理中')
      this.setState(2);
      let start: number = new Date().getTime();
      while (new Date().getTime() - start < 1000) {
        continue;
      }
      console.info("处理成功")
      return 'success'
    }
    return 'success';
  }
}

export const globalState = new GlobalState()
  1. 编写业务处理工具类,主模拟业务处理接口请求失败后的重试机制:
import { globalState } from './GlobalState';

class BusinessHandleUtil {
  static handleFlag: boolean = false;
  static handleCount: number = 0

  async handleBusiness(a: number, b: number): Promise<number> {

    return new Promise(async (resolve, reject) => {
      console.info(`开始处理业务`);

      let businessCode = this.handle()
      let result = a + b;
      if (businessCode === '10200000') {
        console.info(`业务处理失败1`);
        globalState.setState(0)
        globalState.lock_.lockAsync(() => {
          let start: number = new Date().getTime();
          while (new Date().getTime() - start < 2000) {
            continue;
          }
          if (businessCode === '10200000') {
            console.info(`业务处理失败2`);
            if (!globalState.isConnected()) {

              let flag = globalState.setLock() // 模拟业务处理
              if (flag === 'success') {
                globalState.retryTime = 0;
                globalState.setState(1);
                resolve(result);
              }
            }
            resolve(result);
          }
        })
      } else {
        console.info(`网络请求成功`);
        resolve(result);
      }
    });
  }

  // 模拟业务处理接口返回信息,一般情况返回成功
  handle(): string {
    globalState.retryTime++;
    let a = 1000;
    while (a < 10) {
      a--;
    }
    return '10200000'
  }
}

const httpTools = new BusinessHandleUtil();

export { httpTools }
  1. 实现ArkTS的并发任务处理界面:
import { httpTools } from './BusinessHandleUtil';
import { taskpool } from '@kit.ArkTS';

// 使用@Concurrent装饰器标记可并行函数
@Concurrent
async function request(num1: number, num2: number): Promise<number> {
  return await httpTools.handleBusiness(num1, num2);
}

@Entry
@Component
struct Index {
  @State message: string = '点击开始执行业务';

  build() {
    Column() {
      Button(this.message)
        .onClick(async () => {
          // 点击文本触发10个并发任务
          for (let i = 0; i < 10; i++) {
            taskpool.execute(request, i + 1, i + 2) // 通过taskpool实现多任务并发执行
              .then(data => {
                console.info("data" + i + ":" + data);
              })
          }
        })

    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

更多关于HarmonyOS鸿蒙Next开发过程中有没有遇到锁的问题?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


标题

这是第一段内容。

这是第二段内容。

不客气,

基本信息

  • 姓名:张三
  • 年龄:28
  • 职业:软件工程师

技能

  • 熟练掌握Java
  • 熟悉Python
  • 了解C++

项目经验

  • 参与开发企业级电商系统
  • 负责模块设计与编码
  • 使用Spring Boot框架

例如异步并发网络请求多次调用特殊接口,可以使用taskPool搭配异步锁来只执行一次。

项目名称

项目描述

  • 状态:进行中
  • 负责人:张三
  • 开始日期:2023-01-01
  • 结束日期:2023-12-31

任务列表

  • [x] 任务一
  • [ ] 任务二
  • [ ] 任务三

备注

备注信息

鸿蒙Next开发中可能遇到的锁问题包括:

  1. 线程同步锁(如互斥锁)使用不当导致的死锁或性能下降;
  2. UI线程与非UI线程操作冲突需使用TaskDispatcher调度;
  3. 分布式场景下的跨设备数据同步需使用DistributedLock;
  4. 数据库操作需合理使用事务锁。

开发者需注意鸿蒙特有的ArkTS/TS语言特性,避免错误使用锁机制。

在HarmonyOS Next开发中确实会遇到锁相关的问题,主要集中在以下几个方面:

  1. 线程同步锁问题
  • 多线程访问共享资源时容易出现竞争条件
  • 建议使用HarmonyOS提供的Mutex或RWLock替代简单的synchronized
  • 注意避免死锁,确保锁的获取和释放顺序一致
  1. UI线程锁问题
  • 在UI线程执行耗时操作会导致界面卡顿
  • 使用TaskDispatcher进行异步任务分发
  • 需要更新UI时使用UITaskDispatcher
  1. IPC通信锁问题
  • 跨进程通信时可能出现死锁
  • 建议使用HarmonyOS的分布式能力时设置合理的超时时间
  • 避免在Binder调用中持有锁
  1. 数据库锁问题
  • 多线程操作数据库时可能出现锁冲突
  • 使用HarmonyOS的关系型数据库的事务机制
  • 考虑将数据库操作放入单独线程

预防建议:

  • 尽量减少锁的粒度
  • 避免在锁内执行耗时操作
  • 使用tryLock()替代lock()防止死锁
  • 合理设计锁的获取顺序

调试技巧:

  • 使用DevEco Studio的线程分析工具
  • 关注系统日志中的锁等待警告
  • 进行压力测试发现潜在死锁
回到顶部