在网上查了一下,说是如果多个线程同时修改 DOM ,可能会导致竞态条件和不可预测的结果。但是微信小程序用的就是双线程啊?所以浏览器用单线程最本质的原因是什么?以及微信小程序为什么要使用双线程?
1
Danswerme 6 天前 via iPhone ![]() 微信小程序的双线程是指渲染层和逻辑层由不同的线程管理。
https://developers.weixin.qq.com/community/develop/article/doc/0000461093c4d8782ff7cf7d95b413 |
2
UnluckyNinja 6 天前 via Android
渲染层两者不都是单线程吗,想另开逻辑线程浏览器也可以用 worker ,worker 不能直接操作 dom
|
![]() |
3
IvanLi127 6 天前
GUI 渲染一般都是单线程的,小程序也是。
chrome 浏览器的 js 执行是在独立线程的,小程序也是。 小程序和 chrome 一样,js 执行完需要改界面也是委托给渲染线程渲染。至少在这层面来说他们没有你说的区别。 |
![]() |
4
heroisuseless OP @IvanLi127 我比较好奇为什么浏览器会设计成这样,微信小程序又设计成那样,以及浏览器为什么不设计成微信小程序这样的
|
![]() |
5
ShineyWang 6 天前 via Android
GUI 有单独的页面更新和渲染逻辑
windows 上我就遇到过另一个线程修改页面导致控件花屏的 |
![]() |
6
IvanLi127 6 天前
@heroisuseless 我搜了下网上关于小程序双线程的文章,感觉是说的浏览器和 chrome 之类的现代浏览器是不同的。浏览器那么多,你说的是哪个?
|
7
coolcoffee 6 天前
微信小程序的方式只是同一个页面中渲染和逻辑是分离的,UI 层面本质上还是 webview 在绘制,这个 Android 手机上打开调试模式就可以看到页面栈或者 tab 页面都是一个独立的 webview 。
我所了解的除了浏览器渲染,其他像 iOS 原生、Android 原生、Unity 游戏开发都是只能在 UI 线程也称主线程上操作。 最阻碍技术推进的原因肯定是复杂度和收益不成正比。比如本来只通过主线程操作可以进行脏检查来加快一帧数据渲染,但是多线程下面就歇菜了。 |
![]() |
8
tcper 6 天前
小程序的双线程,本质上就是阉割了 webview ,通过他们的框架/IDE/runtime 将逻辑放在他们定制的逻辑线程里执行,然后通过 setData 通知 webview 更新,这么做他们的理由就是内容可控、安全什么的,当然有一定的道理。
所以说小程序所谓的双线程是没有太多技术创新的,因为只是嫁接在 webview 上实现的功能,而且他们的目的也不是技术创新,只是为了实现自身可控的 runtime 。 |
![]() |
9
powersee 6 天前
几乎所有 GUI 渲染都是单线程的,多线程渲染很容易出现死锁、竞争等问题。
|
![]() |
10
araraloren 6 天前
多线程带来的问题大于能带来的好处,除非有更好的架构真的能让你的程序有特定的优点。
|
![]() |
11
shadowyue 6 天前 ![]() 你别想复杂了,现实生活中画画这个行为就无法多人合作。
你见过有十个画师同时画一张色图吗? A 画师绘制巨乳的时候,别人就只能去画美腿。 能优化的只有分图层,分模块,这一部分 GPU 级别就已经做了很多优化了。 现实世界做不到的事情,程序上也做不到。代码也是现实世界的映射。 |
12
kaedeair 6 天前
所有的 gui 程序中更新界面的工作都只能交给一个线程
|
13
leonshaw 6 天前 via Android
因为一个线程够了
|
14
4kingRAS 6 天前 ![]() 我刚学编程时深入研究过这个问题,不只是浏览器这么做,任何涉及 UI 的框架都是单线程模型,QT, Android ,Swing ,WPF ,MFC 等等等等。结论其实就很简单,也很笼统,就是多线程就是不好的设计,有时候为了加速不得已才引入的多线程。平时开发都是能不多线程就不多线程。
几个链接自己研究去吧 https://zhuanlan.zhihu.com/p/44639688 https://flylib.com/books/en/2.558.1/why_are_guis_single_threaded_.html https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/threading-model?view=netframeworkdesktop-4.8 |
15
4kingRAS 6 天前
微信小程序那个问题是为了实现热更新使用了 web 技术,而 webview UI 和 js 都在一个线程,JS 里执行一些耗时逻辑,UI 不就直接卡死了,所以分了双线程 UI 和 逻辑
|
![]() |
16
GeekGao 6 天前
|
17
thevita 5 天前
本质就是 小程序不想让你操作 DOM, 只提供封装后的给你, UI 的实现就可以有私有实现(比如 暴露一些 wx 内部的 API/控件 什么的出去)
浏览器为什么不这么设计: 因为原来没有这样的需求 这里 独立的 JS 线程 就是 个 没有 web api javascript instance (因为所谓的 “多个线程同时修改 DOM ,可能会导致竞态条件和不可预测的结果”,就是 web api 不提供线程安全性),现代 web 浏览器里也是有的,就是 Web Worker , 只是小程序,的与 UI 线程的通信/交互啊什么的都是封装好了的,Web Worker 里你得自己来 |
![]() |
18
ZztGqk 5 天前 via iPhone
不是有 worker 么,只是没有好用的协程切换工具,相比之下原生安卓的配合 kt 的协程是个不错的设计。在 js 这你只能通过 ipc 来实现 worker 通信。
|
19
zhbhun 5 天前 ![]() 问题 1:"在网上查了一下,说是如果多个线程同时修改 DOM ,可能会导致竞态条件和不可预测的结果。但是微信小程序用的就是双线程啊?"
回答:微信小程序的双线程指的是逻辑线程和渲染线程,其中逻辑线程一样也是无法直接同步修改 DOM 的,需要通过 bridge 通信的方式告诉渲染线程来操作 DOM 。其实浏览器也可以做类似的事情,就是把逻辑代码放 web worker 来执行(类似小程序的逻辑线程),现在的 js 线程只接收 web worker 传来的信息进行渲染。社区也有人探索类似的方案,比如 https://github.com/web-perf/react-worker-dom ,就是把 react 搬到 web worker 上运行。 问题 2:“所以浏览器用单线程最本质的原因是什么?” 回答:个人感觉更多是因为早期 JS 就是个脚本语言,主打就是要简单易用,如果引入了多线程会变得更加复杂,当时也没有这个需求。 问题 3:微信小程序为什么要使用双线程? 回答:上面说的 react-worker-dom 虽然类似小程序采用了双线程,但是咋没有流行呢?主要还是因为浏览器的性能瓶颈在 DOM 的渲染上。如果要在浏览器上做一个类似原生应用或微信小程序的页面切换,很容易出现页面切换时卡顿的问题。如果有尝试用过 ionic 来开发 hybrid app ,你会发现页面的切换始终会有存在掉帧的问题,特别是页面 DOM 数量多了。而微信小程序直接每个页面就是新的一个 webview ,交给原生来切换。 另外,客户端那边操作 UI 也必须是在主线程上的,不允许在其他线程直接操作 UI ,客户端为什么更流畅,主要还是因为 JS 本身性能有差距,还有就是 DOM 的渲染性能比原生差很多。记得早起还有人尝试过放弃 DOM ,自己用 canvas 来做一套渲染引擎来优化渲染性能。 |
![]() |
20
codehz 5 天前
微信小程序和 react native 的方案导致了如果直接实现动画,会比较“不跟手”,即存在操作延迟,对于按钮这类交互控件倒是没有啥影响,但滚动的时候就会较为明显,于是微信小程序和 react-native 都各自发明了在 ui 线程里跑代码的方案
|
![]() |
21
heroisuseless OP @zhbhun 感觉明白多了🙏
|
22
charlie21 5 天前
修改 DOM 和渲染 DOM 是不同的意思。抛开浏览器环境里,考虑一个大型游戏软件,为了提升游戏性能 必然要用到多线程,修改状态的线程当然可以是多个,即使渲染线程只能是一个。
|
![]() |
23
wangtian2020 5 天前
因为 JavaScript 的 web api 里有能直接操作 DOM 的 API
|
24
cj323 4 天前
好问题,我之前也发现不只浏览器,web ,android ,ios 都是只有一个 UI thread 。
楼上说浏览器里面简单,但是用 C/C++/C#开发大型游戏的时候也只见过一个 Game loop 。 不知道有没有高人解答一下。 |
![]() |
25
VchentozV 4 天前
https://stackoverflow.com/questions/3261370/is-main-thread-the-same-as-ui-thread
https://stackoverflow.com/questions/1652799/multiple-ui-threads-on-the-same-window 以前我也被别人问过为什么 win32 的主线程一般都是 UI 线程 1. 惯例 => 很多程序习惯这样设计了, 导致后面的一些列东西都是围绕这个惯例来的吧 而且 win32 背后其实是微软的操作系统级别的消息队列, 单个 UI thread 不断去 PeakMessage 就够了. 2. 不要在主线程里面做 data intensive 的操作, 否则会导致 卡顿 3. 就是多个 UI, 可能会有 race condtion. |
![]() |
27
VchentozV 4 天前
不负责任(根据本科组成原理的知识)盲答:
另外, 就算加入 GPU 来渲染, CPU 和 GPU 的工作机制, 早期是共享内存, 然后 DMA 去取, 考虑时序的话, 这本质上还是单个 UI thread + 消息队列就能解决的问题, |