鸿蒙开发中的锁机制

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

鸿蒙(HarmonyOS)开发中,锁机制是保障多线程安全的核心工具,主要包括运行锁(RunningLock)文件锁、异步锁(AsyncLock)等类型。

一、运行锁(RunningLock)

作用:防止系统进入休眠或屏幕关闭,适用于后台持续任务(如音乐播放、导航)。

1. 核心API
方法说明权限要求
isSupported(type: RunningLockType)检查锁类型是否支持
create(name: string, type: RunningLockType)创建锁实例ohos.permission.RUNNING_LOCK
lock()持锁需已创建锁实例
unlock()释放锁需已持锁

2. 代码示例

import { runningLock } from '@kit.BasicServicesKit';

// 1. 检查支持性
let isSupported = runningLock.isSupported(runningLock.RunningLockType.BACKGROUND);
console.log(`BACKGROUND锁支持: ${isSupported}`);

// 2. 创建并持锁
runningLock.create('music_lock', runningLock.RunningLockType.BACKGROUND)
  .then((lock) => {
    lock.lock(); // 持锁
    console.log('锁已持有,屏幕保持常亮');
    // 模拟任务结束后释放
    setTimeout(() => {
      lock.unlock();
      console.log('锁已释放');
    }, 5000);
  })
  .catch((err) => {
    console.error('锁操作失败:', err.code);
  });

注意:需在module.json5中声明权限:

{
  "requestPermissions": [
    { "name": "ohos.permission.RUNNING_LOCK" }
  ]
}

二、文件锁

作用:控制多线程/进程对文件的并发访问,分为阻塞式非阻塞式

1. 核心API
方法说明
lock(exclusive?: boolean)阻塞式加锁(默认独占锁)
tryLock(exclusive?: boolean)非阻塞式加锁,失败立即返回
unlock()释放锁

2. 代码示例

import fs from '@ohos.file.fs';

// 1. 打开文件
let file = fs.openSync('/data/test.txt', fs.OpenMode.READ_WRITE);

// 2. 加独占锁(阻塞式)
fs.lock(file.fd, true).then(() => {
  console.log('文件锁已获取');
  // 写入操作
  fs.writeSync(file.fd, '写入数据');
  // 释放锁
  fs.unlock(file.fd);
}).catch((err) => {
  console.error('加锁失败:', err);
});

// 3. 非阻塞式尝试加共享锁
if (fs.tryLock(file.fd, false)) {
  console.log('共享锁已获取');
  fs.unlock(file.fd);
} else {
  console.log('加锁失败,文件被占用');
}

三、异步锁(AsyncLock)

作用:解决ArkTS共享容器(如collections.Array)的线程安全问题。

1. 核心API
方法说明
lockAsync(callback: () => void)异步加锁,执行回调后自动释放
tryLock()尝试加锁,返回是否成功

2. 代码示例 

import { ArkTSUtils, collections } from '@kit.ArkTS';

@Concurrent
async function modifyArray(arr: collections.Array<number>, lock: ArkTSUtils.locks.AsyncLock) {
  await lock.lockAsync(() => {
    arr[0] += 1; // 安全修改
  });
}

@Entry
@Component
struct Index {
  private lock = new ArkTSUtils.locks.AsyncLock();
  private arr = collections.Array.create<number>(1, 0);

  build() {
    Button('修改数组')
      .onClick(async () => {
        await modifyArray(this.arr, this.lock);
        console.log('数组值:', this.arr[0]);
      })
  }
}

四、线程间同步锁(TaskPool/Worker)

场景:TaskPool适合独立任务,Worker适合关联任务。

1. TaskPool示例
import { taskpool } from '@kit.ArkTS';

@Concurrent
function syncTask(num: number): number {
  // 模拟同步操作
  return num * 2;
}

let task = new taskpool.Task(syncTask, 5);
taskpool.execute(task).then((res) => {
  console.log('任务结果:', res); // 输出10
});
2. Worker示例
// 主线程
let worker = new worker.ThreadWorker('entry/ets/workers/MyWorker.ts');
worker.postMessage({ type: 'calc', data: 10 });

// Worker线程(MyWorker.ts)
worker.onmessage = (msg) => {
  if (msg.type === 'calc') {
    let result = msg.data * 2;
    worker.postMessage(result);
  }
};

五、锁类型对比与选型

锁类型适用场景线程安全是否需要权限
RunningLock系统资源保持(如CPU/屏幕)RUNNING_LOCK
文件锁文件读写同步
AsyncLockArkTS容器操作
TaskPool/Worker多线程任务协调

六、总结

  1. 减少锁粒度:尽量缩小加锁代码范围,避免长时间持锁。
  2. 避免死锁:确保锁的获取和释放成对出现,尤其是异常场景。
  3. 性能监控:使用HiTraceMeter分析锁竞争情况(API 19+支持) 。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值