DSAppTeam / Anchors

:white_check_mark: Anchors 是一个基于图结构,支持同异步依赖任务初始化 Android 启动框架。其锚点提供 "勾住" 依赖的功能,能灵活解决初始化过程中复杂的同步问题。参考 alpha 并改进其部分细节, 更贴合 Android 启动的场景, 同时支持优化依赖初始化流程, 自动选择较优的路径进行初始化。
Apache License 2.0
820 stars 79 forks source link

removeAnchorTask 疑问 #14

Closed hcjcch closed 4 years ago

hcjcch commented 4 years ago
static void removeAnchorTask(String id) {
    if (!TextUtils.isEmpty(id)) {
        sAnchorTaskIds.remove(id);
    }
}

这个方法会多个线程调用,感觉存在线程安全问题

YummyLau commented 4 years ago

@hcjcch sAnchorTaskIds 是线程可见变量,anchor 只有一个,当多个线程 remove 查询之前,会先查询 sAnchorTaskIds 集合是否存在,如果存在再删除。理论上不会有线程问题。如果方法上锁并行校验同步的也有稍微损耗。

hcjcch commented 4 years ago

我觉得线程可见性并不能保证原子性,另外代码中是在 toFinish 中调用 removeAnchorTask 的,这里确实存在并发调用 removeAnchorTask 的问题。我写了代码测试这种情况,出现问题的概率很低。但是这里是不是还是应该做一下线程保护,毕竟是启动框架,稳定性是最重要的。

YummyLau commented 4 years ago

@hcjcch 明白你的意思,可见性只是保证获取的变量是最新的。但是由于树中anchor的节点是唯一的,操作实际上是method被栈调用之后,真正会remove的场景会是唯一的。嗯嗯,后续优化版本我可以保护。 感谢建议。

hcjcch commented 4 years ago

anchor 节点唯一可否详细解释一下,没看太懂,谢谢!

YummyLau commented 4 years ago

anchor 节点唯一可否详细解释一下,没看太懂,谢谢!

anchor场景的节点唯一指的是set控制的某个节点删除调用方法删除自己时,id是一样的。所有remove下删除一个节点只会有一个task成功,但是还是有点问题,具体见下。 今天特地测试了下。由于底层并发是使用map处理的,存在非常低的概率,但是为了保证不必要的问题,后续还是会优化下。 非常低的概率性的原因是,我们的添加和删除不是并非的,只有删除可能并发。而且并发出现问题的场景是,初始化树中,有两条初始化分支同时是异步执行的,同时某个节点run任务同时执行结束,且这两个节点同时被业务设置为anchor。那么第一个remove成功之后,第二个remove成功后可能把第一个remove丢失。 😬😬

hcjcch commented 4 years ago

明白了,感谢大佬!