华为仓颉语言初识:并发编程之同步机制(上)

前言

线程同步机制是多线程下解决线程对共享资源竞争的主要方式,华为仓颉语言提供了三种常见的同步机制用来保证线程同步安全,分别是原子操作,互斥锁和条件变量。本篇文章详细介绍主要仓颉语言解决同步机制的方法,建议点赞收藏!

同步机制

原子操作

和 java 一样,仓颉也支持使用原子操作(Atomic)用来确保多线程下的数据访问安全。主要是提供整数类型,布尔类型和引用类型三种方式。

以整数类型为例,原子变量 Atomic 包括 8 位(AtomicInt8) 至 64 位(AtomicInt64)的整数类型,同时支持基本数据的读写。

  1. 不使用原子操作,在多线程情况下对数据进行累加。
bash 复制代码
  var sum: Int64 = 0

  for (pattern in 1..100) {
         spawn {
          sum += 1               
            }
         }
  sleep(Duration.second*2)
 AppLog.info("Main===${sum}") 

//输出  Main===96
  1. 使用原子变量 AtomicInt64 对数据进行累加。
scss 复制代码
  var sum = AtomicInt64(0)

  for (pattern in 1..100) {
         spawn {
           sum.fetchAdd(1)
            }
         }
  sleep(Duration.second*2)
  AppLog.info("Main===${sum.load()}")

//输出  Main===99

原子操作 Atomic 使用compareAndSwap 用于数据的交换,使用的和 Java 中一样的 CAS 同步机制用于确保在多线程的情况下能够交换成功。

可重入互斥锁

仓颉语言中同样支持使用可重入互斥锁(ReentrantMutex)来解决多线程的同步问题。当一个线程获取到共享变量的锁时,在该线程释放锁之前,其他线程都无法访问该共享变量,直到该线程持有的同步锁释放。

ReentrantMutex 可重入互斥锁主要提供了三个方法 ,分别是 lock(),unlock(),tryLock()。lock()和 unlock()总是成对出现的,及对共享变量加完锁后,等使用结束必须及时释放锁。

lock()和unlock()

还是以在多线程下对数据进行累加操作。

scss 复制代码
  var sum = AtomicInt64(0)
  let mutex =  ReentrantMutex()
  for (pattern in 1..100) {
         spawn {
            mutex.lock()
            sum +=1
             mutex.unlock()
            }
         }
  sleep(Duration.second*2)
  AppLog.info("Main===${sum}")

//输出  Main===99

ReentrantMutex 作为可重入互斥锁,当已经获取互斥锁的线程再次获取该互斥锁时,可以直接获取。但是该线程获取几次互斥锁就需要释放几次锁。

tryLock()

tryLock 表示线程尝试去获取锁,但是并一定能够获取到。可以通过 tryLock()返回到布尔值判断该线程释放获取到锁,然后调用 unLock 释放锁。

Monitor

Monitor 是一个内置锁,继承于ReentrantMutex 可重入互斥锁。Monitor 不仅可以使用 lock(),unlock(),tryLock() 还提供了 wait(),notify(),notifyAll()三个方法用于解决线程间的数据安全问题,这一点和 java 不同,java 中的 Object 提供了 wait(),notify(),notifyAll()三个方法。而 在仓颉中是单独封装的类。

下面举例说明:

kotlin 复制代码
let fun = spawn {
                 monitor.lock()
                 while (flag) {
                 AppLog.info("Main=== thread 1 开始执行")
                 monitor.wait()
                 AppLog.info("Main=== thread 1 执行结束")
                           
                 }
                  monitor.unlock()
                }
   sleep(Duration.second)
   monitor.lock()
   AppLog.info("Main=== 主线程开始执行")
   flag = false                     
   AppLog.info("Main===主线程执行结束")                     
   monitor.notifyAll()                     
   monitor.unlock()                    
  fun.get()      

//输出
// Main=== thread 1 开始执行
// Main=== 主线程开始执行
// Main===主线程执行结束
// Main=== thread 1 执行结束

需要注意的是 monitor 的 wait 和 notify/notifyAll 方法使用之前必须要先获取到锁,即 lock()。

总结

仓颉中的多线程并发安全同步机制十分重要,对于会 Java 的小伙伴来说简单容易上手,但是也有一些需要注意的点,比如 notify 调用前必须要获取到线程锁,用完必须释放否则会导致其他线程无法获取到锁,本篇文章就先讲这些,已经学会了的小伙伴,赶快动手试试吧!。

相关推荐
lilian2334 小时前
HarmonyOS 7 新特性(二十五)|智慧手势:意图识别与误触治理
华为·harmonyos
贾伟康6 小时前
【时光清单|14】HarmonyOS ArkTS 主导航实战:统一页面入口、返回路径和参数校验
harmonyos·arkts·arkui·navigation·路由管理
贾伟康11 小时前
【时光清单|05】HarmonyOS ArkTS 倒计时卡片实战:适配 2x2、2x4 与 4x4 多尺寸
harmonyos·arkts·arkui·服务卡片·formextensionability
小雨青年12 小时前
【HarmonyOS 7 悬浮页签深度实战】07 折叠屏、平板与宽窗口的布局适配
华为·harmonyos
熊猫钓鱼>_>14 小时前
鸿蒙AI Agent新范式:从“对话式辅助”到“工程化代理”的Harness架构实战解析
人工智能·笔记·学习·华为·架构·harmonyos
大锅盖114 小时前
HarmonyOS ArkUI 非遗纹样素材平台设计复盘:朱砂宣纸与鎏金黛蓝的文化守护
华为·harmonyos
2501_9197490314 小时前
华为鸿蒙管理学习生活与工作APP—小羊管理
学习·华为·生活·harmonyos·鸿蒙
贾伟康14 小时前
【时光清单|20】HarmonyOS ArkTS AppGallery 发布复查实战:核对包名、版本、设备、素材和离线声明
harmonyos·arkts·agc·appgallery·发布复查
lilian23315 小时前
HarmonyOS 7 新特性(二十三)|hiprofiler + hidumper:跨堆内存分析
华为·harmonyos
嵌入之梦16 小时前
鸿蒙OS IoT设备开发之基础 —— 外设驱动
物联网·华为·harmonyos