@@ -1746,7 +1746,13 @@ export let exec: execType<worldState> = (worldState, { getStatesFunc }) => {
1746
1746
## 遵循的设计原则在UML中的体现?
1747
1747
1748
1748
1749
- TODO finish
1749
+ 多线程模式主要遵循下面的设计原则:
1750
+ - 单一职责原则
1751
+ 每个线程只做自己的事情,只更新自己的数据,这样就减少了各个线程之间发生冲突的可能性
1752
+ - 最少知识原则
1753
+ 其它线程之间互相不知道,它们只知道主线程;
1754
+ 线程之间只知道发送过来的与该线程相关的数据
1755
+
1750
1756
1751
1757
1752
1758
# 应用
@@ -1758,15 +1764,16 @@ TODO finish
1758
1764
1759
1765
## 缺点
1760
1766
1761
- - 如果需要同时支持单线程和多线程运行环境的话,则需要同时维护单线程和多线程的这两个管道的代码
1762
- 好消息是因为使用了管道模式,所以进行了充分的解耦,使得这两套代码互不影响
1767
+ - 如果需要同时支持单线程和多线程运行环境的话,需要同时维护单线程和多线程的这两个管道的代码,它们有很多逻辑是重复的
1768
+ 好消息是因为使用了管道模式,所以进行了充分的解耦,两套代码互不影响
1769
+ 另外,可以把重复的逻辑提出来放到公共的utils模块中,然后让这两个管道的Job调用它们,从而可消除重复代码
1763
1770
1764
- - 需要考虑考虑线程之间的同步
1771
+ - 需要考虑线程之间的同步
1765
1772
好消息是不需要锁,而是通过共享和备份来实现同步,这样更易于维护且性能更高
1766
- 要实现这种同步的话,可从下面几个方面来考虑 :
1767
- 共享的数据尽量使用不可变数据,因为修改它不需要同步 ;
1768
- 其它线程尽量只读主线程的数据 ,这样就不需要同步;
1769
- 设计同步时,从数据的角度出发 ,识别出主线程哪些数据会被其它线程写;然后备份这些数据,并让其它线程写该备份数据;最后在同步时从备份中更新主线程数据
1773
+ 要使用这种同步方案的话,需要注意下面几个方面 :
1774
+ 共享的数据尽量使用不可变数据,这样修改它们后不需要同步 ;
1775
+ 其它线程尽量只读而不写主线程的数据 ,这样就不需要同步;
1776
+ 在设计时,可以从数据的角度出发 ,识别出主线程哪些数据会被其它线程写;然后备份这些数据,并让其它线程改为写到该备份数据中 ;最后在主线程同步时,从备份中更新主线程数据
1770
1777
1771
1778
1772
1779
## 使用场景
@@ -1781,9 +1788,8 @@ TODO finish
1781
1788
1782
1789
可以将渲染的逻辑从主线程移到一个渲染线程来并行地执行
1783
1790
1784
- - 开多个线程来并行地执行一些逻辑,如加载超大模型、进行复杂计算等逻辑
1785
- 可以开一个线程去加载超大模型,开另一个线程去进行复杂计算;
1786
- 每帧的最后在主线程进行同步
1791
+ - 需要处理加载超大模型、进行复杂计算等并行逻辑
1792
+ 对于有这些并行逻辑的系统,可以开多个线程来并行地执行一些逻辑,具体如可以开一个线程去加载超大模型,开另一个线程去进行复杂计算;每帧的最后在主线程进行同步
1787
1793
1788
1794
1789
1795
@@ -1792,12 +1798,12 @@ TODO finish
1792
1798
1793
1799
- 如果其它线程需要写主线程的数据,则需要同步
1794
1800
1795
- - 使用SharedArrayBuffer时,需要启用跨域隔离
1801
+ - 使用SharedArrayBuffer时,需要启用浏览器的跨域隔离
1796
1802
1797
1803
1798
1804
# 扩展
1799
1805
1800
- - 如果材质有纹理 ,则需要将纹理图片从主线程传到渲染线程,这可以通过浏览器的transferFromImageBitmap API来传送该图片
1806
+ - 如果材质包括了纹理 ,则需要将纹理图片从主线程传到渲染线程,这可以通过浏览器的transferFromImageBitmap API来传送该图片
1801
1807
1802
1808
- 如果是现代图形API,如DX12/Vulkan/Metal/WebGPU,则支持开多个而不是一个渲染线程来渲染
1803
1809
@@ -1854,7 +1860,7 @@ TODO finish
1854
1860
# 更多资料推荐
1855
1861
1856
1862
1857
- 因为游戏的场景一般都比较大,所以游戏引擎一般都支持多线程
1863
+ 因为游戏的场景一般都比较大,所以游戏引擎(如Unity、Unreal)一般都支持多线程
1858
1864
1859
1865
1860
1866
顽皮狗在GDC上提出了Fiber架构,使用了管道模式,支持多线程,具体可在网上搜索“Parallelizing the Naughty Dog Engine using Fibers”
0 commit comments