二十九、【鸿蒙 NEXT】异步锁实现并发控制

【前言】

在开发鸿蒙代码时,经常会用到async的异步函数,假设函数名称是A,如果A函数里面有个异步操作很耗时的话,我们可能会用到缓存,将耗时操作的结果保存到缓存中,如果下次再有调用A函数的话,直接返回缓存中的值。但是有时候,当缓存还没有值的时候,A函数在短时间内被调用多次,导致耗时函数会被执行多次,可能导致阻塞主线程的问题。下面首先复现下这种场景,并给出一个解决方案。

1、模拟一个耗时的异步函数,短时间内被调用多次

代码如下,其中getValue函数表示一个耗时的异步函数,我们用一个for循环执行多次,来模拟短时间被调用多次,我们可以看结果,每次调用,缓存值都还没有生成,这就导致,计算缓存值的函数会被多次执行。

javascript 复制代码
@Entry
@Component
struct LockPage {
  async aboutToAppear() {
    let util = new LockUtil()
    for (let index = 0; index < 4; index++) {
      util.getValue().then((value) => {
        console.log(`[lock] getValue is ${value}`)
      })
    }
  }
  build() {
    RelativeContainer() {
    }
  }
}

export class LockUtil {
  private cache = ''

  public async getValue():Promise<string> {
    if (this.cache) {
      return this.cache
    }
    console.log('[lock] no cache')
    // 模拟耗时操作
    await new Promise<void>(resolve => setTimeout(resolve, 3000));
    this.cache = '6666'
    return this.cache
  }
}

执行结果:

2、使用异步锁ArkTSUtils.locks.AsyncLock控制异步并发

我们这里引入系统的异步锁,来控制异步函数的并发,使得计算缓存的耗时操作只执行一次,代码如下,看日志打印,耗时函数只执行一次,其余都是从缓存中获取

javascript 复制代码
public async getValueLock():Promise<string> {
    if (this.cache) {
      return this.cache
    }
    let lock:ArkTSUtils.locks.AsyncLock = ArkTSUtils.locks.AsyncLock.request('lock')
    let result = await lock.lockAsync(async () => {
      if (this.cache) {
        return this.cache
      }
      console.log('[lock] no cache')
      // 模拟耗时操作
      await new Promise<void>(resolve => setTimeout(resolve, 3000));
      this.cache = '6666'
      return this.cache
    })

    return result
  }

完整代码示例如下:

javascript 复制代码
@Entry
@Component
struct LockPage {
  async aboutToAppear() {
    let util = new LockUtil()
    for (let index = 0; index < 4; index++) {
      util.getValueLock().then((value) => {
        console.log(`[lock] getValue is ${value}`)
      })
    }
  }
  build() {
    RelativeContainer() {
    }
  }
}


import { ArkTSUtils } from "@kit.ArkTS";

export class LockUtil {
  private cache = ''

  public async getValue():Promise<string> {
    if (this.cache) {
      return this.cache
    }
    console.log('[lock] no cache')
    // 模拟耗时操作
    await new Promise<void>(resolve => setTimeout(resolve, 3000));
    this.cache = '6666'
    return this.cache
  }

  public async getValueLock():Promise<string> {
    if (this.cache) {
      return this.cache
    }
    let lock:ArkTSUtils.locks.AsyncLock = ArkTSUtils.locks.AsyncLock.request('lock')
    let result = await lock.lockAsync(async () => {
      if (this.cache) {
        return this.cache
      }
      console.log('[lock] no cache')
      // 模拟耗时操作
      await new Promise<void>(resolve => setTimeout(resolve, 3000));
      this.cache = '6666'
      return this.cache
    })

    return result
  }
}
相关推荐
仓颉编程语言36 分钟前
CangjieSkills 正式开源:为仓颉 AI 编程打造的“技能增强“方案,实测降低 60% 费用
华为·ai编程·鸿蒙·仓颉编程语言
弓.长.2 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-netinfo — 网络状态检测
网络·react native·harmonyos
弓.长.2 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-network-info — 网络信息获取
网络·react native·harmonyos
弓.长.3 小时前
ReactNative for OpenHarmony项目鸿蒙化三方库:react-native-image-crop-picker — 图片选择裁剪组件
react native·react.js·harmonyos
讯方洋哥14 小时前
HarmonyOS App开发——鸿蒙ArkTS基于首选项引导页的集成和应用
华为·harmonyos
左手厨刀右手茼蒿20 小时前
Flutter 三方库 all_lint_rules_community 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、严谨、基于全量社区 Lint 规则的工业级静态代码质量与安全审计引擎
flutter·harmonyos·鸿蒙·openharmony·all_lint_rules_community
雷帝木木20 小时前
Flutter for OpenHarmony:Flutter 三方库 cbor 构建 IoT 设备的极致压缩防窃协议(基于标准二进制 JSON 表达格式)
网络·物联网·flutter·http·json·harmonyos·鸿蒙
王码码203520 小时前
Flutter 三方库 servicestack 的鸿蒙化适配指南 - 实现企业级 Message-based 架构集成、支持强类型 JSON 序列化与跨端服务调用同步
flutter·harmonyos·鸿蒙·openharmony·message-based
里欧跑得慢20 小时前
Flutter 三方库 jsonata_dart 的鸿蒙化适配指南 - 实现高性能的 JSON 数据查询与转换、支持 JSONata 表达式引擎与端侧复杂数据清洗
flutter·harmonyos·鸿蒙·openharmony·jsonata_dart
chenyingjian21 小时前
鸿蒙|性能优化-内存及其他优化
harmonyos