Kotlin线程同步

面试必会的知识点:Kotlin 线程同步的 N 种方法,学会了才能不慌 面试的时候经常会被问及多线程同步的问题,例如: “ 现有 Task1、Task2 等多个并行任务,如何等待全部执行完成后,执行 Task3。” 在 Kotlin 中我们有多种实现方式,本文将所有这些方式做了整理,建议收藏。 Thread.join Synchronized ReentrantLock BlockingQueue CountDownLatch CyclicBarrier CAS Future CompletableFuture Rxjava Coroutine Flow 我们先定义三个T 阅读详情

多线程并发访问共享数据可能导致意外或错误行为。Kotlin 允许我们控制多个线程对任何类型共享资源的访问。解决方案就是线程同步(Thread Synchronization)。


重要术语与概念

在我们开始使用同步前,先了解一些必要的术语和概念:

1)线程同步是一种机制,用于确保两个或多个并发线程不会同时执行一段称为临界区(Critical Section) 的代码。

2)临界区是访问共享资源的代码区域,这段代码不能被多个线程同时执行。共享资源可能是变量、文件、输入/输出端口、数据库等。


我们来看一个例子:有一个名为 Counter 的类,它有一个字段 count:

class Counter {
    var count = 0

    fun inc() {
        count++
    }
}

代码说明:
这个类有一个名为 count 的变量和一个 inc() 方法,该方法用于将 count 增加 1。


现在我们用两个线程对该字段同时进行递增操作,每个线程递增 10,000,000 次:

import kotlin.concurrent.thread

fun main() {
    val counterInstance = Counter()
    val thread1 = thread {
        for (i in 1..10_000_000) {
            counterInstance.inc()
        }
    }
    val thread2 = thread {
        for (i in 1..10_000_000) {
            counterInstance.inc()
        }
    }
    thread1.join()
    thread2.join()
    println("The result of the threads' work: ${counterInstance.count}")
}

代码说明:
我们创建了一个 Counter 实例并启动两个线程,每个线程对 count 执行 1 千万次递增。程序执行完毕后,输出 count 的值。


理论上最终值应该是:20,000,000,但实际运行结果却可能是错误的,比如:

The result of the threads' work: 18696438

这是因为:

  • 某些线程看不到其他线程对共享数据的更改(可见性问题);

  • 某些线程可能看到的是非原子操作的中间值(原子性问题)。

这正是我们在多线程共享数据时所遇到的典型问题,因此多个线程递增一个值就是一个临界区问题。

当然,这只是个简单示例,实际的临界区可能要复杂得多。


同步代码

我们可以用经典方法来保护这段代码,使其不被多个线程同时访问,即使用同步方法。

Kotlin 中有两种方式实现同步:


1. 使用注解 @Synchronized 同步函数:

@Synchronized
fun myFunction() {
    // 执行某些操作
}

说明:
注解是一种为代码附加元数据的方式。在这里,@Synchronized 表示此方法在同一时刻只能被一个线程调用。


2. 使用 synchronized() 函数创建同步块:

fun myOtherFunction() {
    synchronized(this) {
        // 同步代码块
    }
}

说明:
同步方法或同步块需要一个对象来加锁。同一时刻只有一个线程能执行同步块或同步方法中的代码,其他线程将会被阻塞,直到锁释放。


示例:同步函数

函数可以通过注解 @Synchronized 来同步。

同一时刻,一个对象的同步方法只能被一个线程执行;而多个对象的同步方法则可以同时被不同线程执行。

class SomeClass(val className: String) {
    @Synchronized
    fun doSomething() {
        val threadName = Thread.currentThread().name
        println("$threadName entered the method of $className")
        println("$threadName leaves the method of $className")
    }
}

说明:
doSomething() 是一个同步方法,打印出进入和离开该方法的线程信息。


我们再创建一个线程类,调用 doSomething() 方法:

class MyThread(val classInstance: SomeClass) : Thread() {
    override fun run() {
        classInstance.doSomething()
    }
}

然后启动多个线程:

val instance1 = SomeClass("instance-1")
val instance2 = SomeClass("instance-2")

val first = MyThread(instance1)
val second = MyThread(instance1)
val third = MyThread(instance2)

first.start()
second.start()
third.start()

输出可能是:

Thread-0 entered the method of instance-1  
Thread-2 entered the method of instance-2  
Thread-0 leaves the method of instance-1  
Thread-1 entered the method of instance-1  
Thread-2 leaves the method of instance-2  
Thread-1 leaves the method of instance-1  

说明:
没有任何线程在同一时刻执行 instance-1 的方法,说明 @Synchronized 成功起到了同步作用。你可以多次运行它来观察行为。


示例:同步块

有时,我们只希望同步方法的一部分,可以使用 synchronized()。

class SomeClass {
    var value = 0
    fun changeValue(newValue: Int) {

        // 非同步代码
        print("I'd like to change the value for $newValue")
        synchronized(this) {
            // 同步代码
            value = newValue
        }
        print("The value has been changed successfully!")
    }
}

说明:
changeValue() 方法中只有 value = newValue 被加锁。
同步块基于 this 实例加锁,不同实例之间互不影响。

同步块虽然和同步方法相似,但提供了更灵活的控制,你可以只同步必要的代码部分。


总结

多线程中最重要的机制之一——线程同步。
该机制能确保代码在多个线程同时访问共享数据时,能正确安全地运行。
两种同步代码的方式:

  1. 使用 @Synchronized 注解同步整个函数;

  2. 使用 synchronized() 函数同步代码块。

Android Kotlin线程同步的几种技术 本文介绍了Android Kotlin中几种常用的线程同步技术,包括互斥锁、信号量、条件变量和屏障。根据具体的需求,我们可以选择适当的线程同步方法来实现多线程操作。本文将介绍几种常用的线程同步方法,并提供相应的源代码示例。信号量是一种常用的线程同步机制,它可以控制同时访问某个共享资源的线程数量。屏障是一种线程同步机制,它会阻塞一组线程,直到满足某个条件后才释放它们。条件变量是一种同步机制,用于在多线程环境下实现线程间的通信。这样,每次只有一个线程可以执行这些方法,从而确保了数据的正确性。 阅读详情

相关推荐

Android kotlin线程同步的几种方法

在app开发中,现在主流语言已经开始用kotlin 那么对于线程同步也是在工作中常用的 那么今天就来讲解5中线程同步的方法 先用示例代码看如何实现同步 val task_one: () -> String = { sleep(200) "kotlin".also { Log.e("TAG","task_one finished: $it") } } val task_two: () -> String = { sleep(200) "android".also

安卓兼职framework和app工程师的博客 1722

Kotlin:该如何实现多线程同步?

1.1 协程是什么1.2 什么是Job 、Deferred 、协程作用域1.3 Kotlin协程的基础用法。

Gaga246的博客 1507

加拿大程序员趣闻系列:Kotlin多线程同步在Android中的应用

在main函数中,我们创建了两个线程,一个线程调用increment方法,另一个线程调用decrement方法。除了使用synchronized关键字之外,Kotlin还提供了其他一些同步机制,例如使用ReentrantLock类实现线程锁。本文将详细介绍在Android中使用Kotlin进行线程同步的方法,并提供相应的源代码示例。在Kotlin中,我们可以使用synchronized关键字来实现线程锁。在每个方法中,我们先调用lock方法获取锁,然后在finally块中调用unlock方法释放锁。

2301_78484069的博客 256

Kotlin 中的同步与异步执行:run、runCatching、runBlocking 与 runInterruptible

在最近,观看了一段关于的视频,这是对行为的一个良好的解释。runBlocking 文档强调了几个关键限制和建议:• 不应该在协程中使用。• 将常规阻塞代码桥接到以挂起方式编写的库• 用于 main 函数• 用于测试。从run和开始。首先,run和是同步的,而和是异步的。run和是 Kotlin 标准库的一部分,可以在所有支持的平台上使用。和是 Coroutines 的一部分。最好通过例子来理解。

chuyouyinghe的专栏 2087

STM32 CubeMX实战:手把手教你用I2C驱动IST8310磁力计(附完整代码)

本文详细介绍了如何使用STM32 CubeMX和I2C驱动IST8310磁力计,从硬件连接到代码实现的完整流程。重点讲解了I2C通信异常处理、传感器初始化序列优化以及中断驱动数据采集方案,帮助开发者快速搭建可靠的地磁场数据采集系统。

weixin_42531163的博客 190

保姆级教程:Halcon 3D点云匹配与差异分析避坑指南(从采样到可视化)

本文提供了一份详细的Halcon 3D点云匹配与差异分析实战指南,涵盖从模型准备到可视化的全流程。重点解析了STL文件读取单位误区、点云采样密度优化、表面模型创建技巧以及差异分析的专业手法,帮助用户避开常见陷阱,提升工业检测效率与精度。

weixin_33728268的博客 402

kotlin-协成同步

kotlin协成同步代码,实现等待前者执行完后再执行后面代码

lovelixue的博客 1177

基于图神经网络的社交网络虚假账号检测系统 (Graph-based Fake Account Detection System, GFADS)

FOLLOWSRETWEETSSHAREDCOMMENTSLIKESMENTIONSUseruser_idusernamejoin_datebioavatar_urllocationverifiedis_fakeLOAD CSV这是决定模型性能的关键环节,需结合和。XXedge_indexy新账号缺乏历史数据和丰富关系。全网图可能包含数亿节点和数十亿边,难以直接训练。社交网络是动态变化的,虚假账号策略也在不断进化。获取大规模、高质量的真实/虚假账号标注数据非常困难。

Deng945201314的博客 1481

Kotlin 线程同步的 N 种方法

面试的时候经常会被问及多线程同步的问题,例如: “ 现有 Task1、Task2 等多个并行任务,如何等待全部任务执行完成后,开始执行Task3 ?” Kotlin 中有多种实现方式可供选择,本文将所有这些方式做了整理: Thread.join Synchronized ReentrantLock BlockingQueue CountDownLatch CyclicBarrier CAS Future ...

chuyouyinghe的专栏 3148

Vercel静态站被墙别慌!手把手教你用Cloudflare免费CDN+域名解析搞定DNS污染

本文详细介绍了如何利用Cloudflare免费CDN和域名解析解决Vercel静态网站遭遇DNS污染的问题。通过诊断DNS污染、设计Cloudflare解决方案架构、实战配置步骤以及高级调优技巧,帮助用户快速恢复站点访问并提升防护能力。

weixin_27442001的博客 704

ESP32连接PDM麦克风操作指南:新手入门必看

手把手教你如何将ESP32与PDM麦克风连接,采集音频数据并用于音频分类应用。内容涵盖硬件接线、代码配置及实际调试技巧,适合初学者快速上手esp32在声音识别场景中的使用。

weixin_42590539的博客 1329

面试必备:Kotlin 线程同步的 N 种方法

面试的时候经常会被问及多线程同步的问题,例如: “ 现有 Task1、Task2 等多个并行任务,如何等待全部执行完成后,执行 Task3。” 在 Kotlin 中我们有多种实现方式,本文将所有这些方式做了整理,建议收藏。 1. Thread.join2. Synchronized3. ReentrantLock4. BlockingQueue5. CountDownLatch6. CyclicBarrier7. CAS8. Future9. CompletableFuture10. Rxjava11

Androidbye的博客 675

从Level 1到Level 22:手把手带你用Burp Suite通关burp-labs靶场全关卡(附难点解析)

本文详细解析了如何使用Burp Suite通关burp-labs靶场的22个关卡,从基础爆破到复杂编码绕过,涵盖Intruder配置、响应过滤、POST请求处理、MD5爆破等关键技术。特别针对Level 16的三重编码和Level 20的中文响应处理等难点提供实战技巧,帮助渗透测试工程师提升Web安全实战能力。

weixin_28831461的博客 436

Kotlin 的锁和多线程同步

作为结论,在 Kotlin 上最好用的线程同步方案首推协程。作者:JeffreyWorld链接:https://www.jianshu.com/p/7dbd035d152d来源:简书著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

chuyouyinghe的专栏 3787

PINN:当深度学习遇上朗伯-比尔定律

光谱数据处理中引入PINN的三种架构设计

qq_53529450的博客 154

基于 51 单片机的智能手势控制小车设计与实现

智能手势控制小车以STC89C52RC 单片机为控制核心,通过手势识别模块采集用户手势指令,经单片机处理后驱动电机执行前进、后退、左转、右转等动作。该项目融合了传感器技术、单片机编程和电机驱动技术,具有成本低、易实现、互动性强的特点,适合作为嵌入式系统入门实践案例。本项目成功实现了基于 51 单片机的智能手势控制小车,通过 APDS-9960 模块采集手势信号,经单片机处理后驱动电机完成基本动作,验证了 “传感器 + 单片机 + 执行器” 的嵌入式系统设计思路。

weixin_42300449的博客 180

Kotlin多线程同步实战:Synchronized与Volatile的深度解析

本文深入解析Kotlin多线程同步中Synchronized与Volatile的应用场景与实现原理。通过对比两者的特性差异,结合实际代码示例,帮助开发者解决共享状态管理的核心挑战,包括可见性问题和原子性问题。文章还提供了性能优化技巧和现代Kotlin中的替代方案,如Atomic类和协程Mutex。

zero1的博客 1030

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

动手实现Kotlin协程同步切换线程,以及Kotlin协程是如何实现线程切换的

前言 突发奇想想搞一个同步切换线程的Kotlin协程,而不用各种withContext(){},可以减少嵌套且逻辑更清晰,想实现的结果如下图: 分析 实现我们想要的结果,首先需要知道协程为什么可以控制线程的切换以及在挂起函数恢复的时候回到原来设定的线程中 ps:挂起函数比普通函数多出了两个操作:挂起和恢复,具体参考:https://blog.youkuaiyun.com/qq_33505109/article/details/109066392 其实控制线程切换是协程库内内置的一个拦截器类:Continu

lt的博客 3608

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Kotlin协程实现多线程异步执行到同步获取结果

通过async执行异步任务, 然后通过wait获取异步任务的返回结果, 类似的原理和Java的join类似, 在调用wait之前就已经线程开始了, wait的作用只是为了获取协程的执行结果, 获取不到就wait.flow让我想起RxJava的一些操作符, 又麻烦又不实用, 平添记忆负担. 对flow的一种使用情况进行测试, 其他情况可能有能够异步执行的方式, 下面方式实际上没有做到多线程异步, 最后还是同步一个个的执行.带launch的分别对应不同的子线程。带result的都会在当前线程打印。

有速度的空气的博客 1315

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

【面试必知】Kotlin并行任务/线程同步的几种实现方式

多线程开发中,经常会遇到这样的需求: Task1、Task2 等多个任务并行执行,等待全部执行完成后,执行Task3。 我们在Kotlin种可以有多种方法实现,在这里一并列举一下: 1. Thread.join 2. synchronized 3. ReentrantLock 4. BlockingQueue 5. CountDownLatch 6. CyclicBarrier 7. CAS 8. Future 9. CompletableFuture 10. Rxjava 11. Coroutine

移动端开发干货分享 6752

kotlin 线程同步

为什么80%的码农都做不了架构师?>>> ...

weixin_34029949的博客 2507
上一篇: 多线程数据共享
下一篇: 集合与多线程
Kiri霧
博客等级 码龄3年 432粉丝 156原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值