(基于Nordic)Android 蓝牙mesh协议栈问题修复之-节点并发问题处理

5 篇文章 0 订阅
4 篇文章 0 订阅

背景

  • 首先贴上官方github地址https://github.com/NordicSemiconductor/Android-nRF-Mesh-Library
  • 本次修改基于官方SDK 2.4.1版本.
  • 阅读此文章之前,我们默认您对蓝牙mesh协议已经有了一定了解.
  • 本次修复了两个问题,一个是节点对于数据库读写的并发问题,另一个问题是对于蓝牙包的单播消息序列对应的问题.

1.节点数据库读写的并发问题

问题分析

起初遇到这个问题,是因为app总是会crash,会出现CME(ConcurrentModificationException),出现这个原因是因为我们mesh中保存节点的数据对象使用的ArrayList,而ArrayList是线程不安全的.在并发的情况下,如果对ArrayList同时进行读写,就会出现CME,从而导致crash,而在我们的应用场景中,对设备同时进行读写的场景比较频繁,所以我们
为了避免出现CME的情况,我们需要应对这种处理场景.

修改内容

经过研究,我们找到了CopyOnWriteArrayList,来替代ArrayList,以保证并发场景下的读写问题.为什么可以保证并发读写,这里我们简单解释一下,CopyOnWriteArrayList在写数据的时候,会先将里面的数组copy出来,进行修改之后,再copy回来.这样就达到了读写分离的效果了.这也是未来语言代码设计的趋势.比如现在很流行的kotlin,就将读写分离的思想,完全融入到语言设计当中去了.

对于并发节点的修改,涉及到很多地方,这里就不一一列举出来了.大致修改了三个list的并发场景,就是NetworkKey,ApplicationKey,ProvisionedMeshNode三个数据的节点列表的并发场景.如下:

    List<NetworkKey> netKeys = new CopyOnWriteArrayList<>();
    @Ignore
    @SerializedName("appKeys")
    @Expose
    List<ApplicationKey> appKeys = new CopyOnWriteArrayList<>();
    @Ignore
    @SerializedName("nodes")
    @Expose
    List<ProvisionedMeshNode> nodes = new CopyOnWriteArrayList<>();

既然在定义的时候,我们对节点进行了修改,那么我们在赋值,节点的导入导出,我们都需要考虑到对数据的处理.

下面还需要注意一点的是,CopyOnWriteArrayList是不支持排序的,因此,在SDK代码中对于数据的排序方法,我们也做了一些小小的修改.改动如下:

        //处理CopyOnWriteArrayList的排序问题
        List temp = Arrays.asList(nodes.toArray());
        Collections.sort(temp,nodeComparator);
        nodes.clear();
        nodes.addAll(temp);

可以看出,我们是先将数组copy出来,放到ArrayList中进行排序完,再放回去.

2.并发消息收发序列的问题

问题分析

对于收发消息序列的问题,这里主要是涉及到应用层消息接收的顺序问题,因为我们如果同时发了多个单播消息,那么我们没办法将回来的消息一一对应起来,这样可能就会出现消息错乱的问题,这是我们不想得到的结果.

修改内容

所以我们可以在应用层,每次发数据的时候,腾出一个字节出来(保证一定是时间内可以处理256个并发),用来记录消息的序列号,(我们一般命名Tid),用这个序列号来记录我发出去的消息序列号,我们让设备端每次处理完消息,返回给我们的时候,再将Tid带回来,等到我们收到数据的时候,我们将Tid再解出来与之前发送的Tid进行匹配,那么就可以将消息一一对应上了.我们现在来画个时序图来表述序列对应的思想:

在这里插入图片描述

因此,问题得到迎刃而解.

如果任何疑问,请联系邮箱:569133338@qq.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值