HIT软件构造经验漫谈(五)

在本课程的第7章中介绍到了多线程,这在实际项目开发中是非常常用的一个操作,也是一个会产生大量难以排查的BUG的操作,本博客通过记录一个我之前开发的程序的debug经历来对多线程进行一个总结

1. 什么是多线程

  这里直接援引课件中的内容,更直观地,可以把一个新的线程,看作是一次fork(他们有相似处,但其实是不太一样的),或者是看作一个异步操作。
在这里插入图片描述

2. 多线程的好处

  在课件中也有提及,这里简单地概括一下就是可以在硬件性能没有显著提升的情况下,极大地提升程序的运行效率。
  直观地,比如我写了一个GUI,需要显示用户的信息,那么我可能就需要向服务器发起一个https请求或者是读取本地的缓存,这就存在延迟,这个时候我不可能就干等着,而是直接继续向下执行程序,让另一个线程来执行这个请求或是进行缓存的读取。否则运行效率就会很差。
  以腾讯的微信小程序开发为例,向腾讯云服务器的一次https请求的延迟大概在100ms上下。如果采取串行编程,这个延迟时间大概够我的程序的其他部分跑10遍了。
在这里插入图片描述
  这是一个读取本地缓存的例子,程序是用JS编写的,大致逻辑是,我定义了一个局部变量tempPlan,通过wx的getStorage方法读取一个key为plan的数据并存储于tempPlan中,然后把读取到的值交给Data域中的plan,如果代码真的这么写,那么plan最终大概率会被赋值为null,而不是读取到的缓存,因为getStorage是一个异步请求,或者说它开启了一个新的线程去进行数据读取和写入。
在这里插入图片描述
这里给出的是正确写法。

3. 多线程可能带来的问题

  最常见也是影响最大的问题就是:interleaving,即代码的交叉执行,在课件中有大量的例子,这里就不在举例子了。

4. 如何处理多线程可能带来的问题

  本课程主要介绍了四种方式:不要共享可变数据,尽量共享不可变数据,共享线程安全的可变数据,锁。
  这里再额外给出一种方法,即通过回调函数的方式,将多线程之间的并行操作转换为串行操作。
在这里插入图片描述
  图中给出的就是一个通过promise来将多个异步请求转换为串行请求。前面说到了将串行转并行是为了提升程序效率,那么我为什么又要把并行转换回串行呢,这是因为我需要保证程序的正确性。
  一方面,我将除了这部分代码以外的部分,和这个promise链通过两个线程(实际运行时未必就是两个线程,也可能是多个,取决于微信的具体实现)来并发地运行,另一方面我把这个promise链中原本并行执行的代码转换为了串行执行。这样我即保证了效率,也保证了正确性。

5. 我的debug经历

  在为我校建校百年开发专属头像小程序时,就遇到了预览头像和头像框时,出现头像框串行的问题。当时调了很久都找不到问题所在,最后突然反应过来可能是时序问题。在通过promise调整了时序后,果然就ok了。
在这里插入图片描述
  这是当时那个小程序的核心部分,预览的机型是iphone5。当时遇见的问题是在用户选择完图片后,在头像样式部分预览的头像框的样式可能会叠加在一起。如果用过同类型的头像框定制小程序,那么应该也见过这种神奇的BUG。其根本原因就在于并发导致的运行时序不确定。
  其实本来想详细记录一下这段漫长的debug经历的,然而大多数内容都是关于JavaScript和微信小程序开发的,放在软构的博客里可能就有点喧宾夺主了,因此就简单的提一嘴叭。。。以后想起来了再写一篇博客详细地记录一下人生第一次和并发的战斗经历。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值