V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  codehz  ›  全部回复第 7 页 / 共 125 页
回复总数  2500
1 ... 3  4  5  6  7  8  9  10  11  12 ... 125  
@xubingok useMemo 是给计算需要一定成本的用的,简单加减乘除甚至字符串连接都不需要。
我觉得你这个例子里用 setState 没有问题,但是扩展到更大项目里,如果每个子元素的更新都要触发 root 组件的更新的话,就有点问题了,这时候可以考虑引入第三方状态管理库来处理
冷知识好多第三方状态管理库也都是接入到 react 的 useState (或者更高级的 useSyncExternalStore )来处理,但是针对复杂嵌套状态做了优化,避免了“牵一发动全身”的问题,只会在用到状态的地方触发 setState (或者 sync external store 里的回调)
虽然 office 365 那边肯定是有简单的解决方案的(你就存 sharepoint 上,点开可以调用本地 office 套件)
136 天前
回复了 unt 创建的主题 程序员 如何防止用户篡改数据
所以要在后端验证啊,你前端验证只是保证用户体验用的
没准可以用浏览器上的 adb (安卓手机可以给另一个安卓手机刷机)
https://github.com/yume-chan/ya-webadb/
141 天前
回复了 ilee1989 创建的主题 JavaScript 求助:前端 JS 加密,防止被爬虫爬
不嫌麻烦的话走 websocket 吧,至少难度上可以给攻击者加一些,能干掉不少低级爬虫框架
141 天前
回复了 tool2d 创建的主题 分享创造 做了一个 unicode 方块字体显示工具
@jimmy3780 但不管它是由几个字符组成的,表现上还是一个字符,就应该渲染成单个字符
你注入样式的方法不对吧,建议将样式注入到 shadowdom 里,而不是插入全局样式,就基本上不会影响页面了 https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components/Using_shadow_DOM
@lesismal 不过 c++内存模型(和 rust 等一些“现代语言”)的巧妙之处就在于,它把硬件的内存模型和编译的优化模型都统一的结合在一起了,只要保证最终目标(执行结果和内存模型预测的一致),就可以完全无视代码本身的执行逻辑,编写顺序
然后一旦加入了屏障,就同时修改编译的优化逻辑,以及加入硬件相关的屏障代码
@rockyliang 立刻就被观测到的一个前提是,真的有去生成读取的代码,虽然我在任何在线 go playground/godbolt 都没能复现这种情况(),但是这个读取的消除理论上是可以做的,毕竟 go 的文档也没说要保证生成读取的副作用,不能开局读一个值,然后就不管了
(用 c/c++可以在 godbolt 里看到这种情况,直接把有条件循环变成死循环)
@RedisMasterNode 其实 sleep10 秒也未必能保证()
多线程编程里,就是要假设任意一个线程可以被饿死任意长的时间,任何使用硬编码数字的 sleep 方法都是不能保证的
单从 store forwarding 角度来说,虽然实际上你可以观测到变量的读取直接从本地 store buffer 里提取之前写入的值来实现跳过全局缓存,但逻辑上仍然属于内存序问题
举例
线程 1
C = -1;

A = 0;
B = 0;
if(B == 1) C = A;
线程 2
A = 1;
B = 1;
在 x86 上可以观测到 C 的值可以是-1 0 1 (完全 TSO 的设备上不可能能是-1 )
即使线程 2 并没有交换 A B 的写入顺序,但这里可以“理解”为线程 1 交换了 C=A 和 if 的执行顺序,C 先=A ,然后再判定 B 是否==1
而高级语言的内存屏障也正是为了这个场景而设计的,通过保证副作用发生的顺序来避免出现意料之外的情况
当然仔细探究的话还有 storebuffer 和 loadbuffer 的相关的东西,但那都是基于推测执行的,也就是说它甚至连本地的缓存都没进,只是相当于“推迟”了写入/读取的副作用,最后积累一批之后再统一让副作用生效,它甚至没到缓存这一侧,而且也不能说是指令执行已经完成了(因为还没写入/读取成功,有数据依赖的指令就会被阻止),当 storebuffer 被实际应用到本地缓存的时候,还是会遵循 mesi 协议去同步其他 cpu 的缓存状态
当然考虑到 store forwarding 的存在,load 请求可能会直接从 storebuffer 里取,跳过了所有其他缓存,但这仍然算是顺序问题,因为这整个过程都是发生在同一个核心里的,副作用最终还是会被应用,无论如何它都不属于多线程的可见性问题
@rockyliang 可见性问题只是 java 自己内存模型里的东西,也不是啥放之四海而皆准的标准。。。事实上除了 java 之外,根本没有别的地方在用这个概念( gpu 相关的倒是有,但是那里的可见性是另一个概念)
本质上 MESI 协议就是让你根本无法察觉缓存的存在,你如果真的有仔细阅读 MESI 协议,就会发现,无论出现什么情况,它都不能被用户态观测到“不一致”的情况,只有有一个核心写入了它自己本地的缓存,另一个核心立刻就会观测并 invalidate 缓存,不可能出现读取到的局部缓存和全局不一致的场景。。。
https://zhuanlan.zhihu.com/p/413889872
这里有个文章解释了 cpu 的这种乱序执行的行为
可以看出和一些编译器的优化也是类似的,只是不受程序员的直接控制,只能通过插入内存屏障来解决
@jokimina 简单说就是 arc 把顶部的地址栏改成了悬浮面板(值得一提的是打开新标签页时,不需要先切换到空白页,再打开网页,这一说是传统地址栏交互逻辑的一大痛点)然后也能在那个面板里进行一些浏览器操作
@rockyliang 不对,不要牵扯到缓存,你直接当缓存不存在,这些问题都是一样的逻辑,你这里引入所谓缓存失效一类的,只是烟雾弹,实际上的问题是 cpu 根本就不一定按源码顺序执行效果,没有缓存的情况下一样会引起问题
142 天前
回复了 tool2d 创建的主题 分享创造 做了一个 unicode 方块字体显示工具
对一些 emoji 支持不行
比如 🐦‍⬛ 会变成三个字符
感觉就是把 arc 浏览器的一个主要功能点实现了()
@yph007595 不是观测不到,最终肯定是能观测到的
主要的问题是过程中,可能会出现另一个线程观察到的修改顺序和你在源代码里看到的顺序不一致
也就是一个线程你明明先改 a 再改 b ,但另一个线程可能会先看的 b 被改,然后 a 才改,你去检测 b 来确保同步的话就会出现问题
这时候才需要引入所谓的内存序和读写屏障的概念
一方面阻止了编译器调换顺序(编译器默认只需要保证在一个线程里的“执行效果”一致,调换顺序不影响结果的话就可以换)
另一方面也阻止了 cpu 的一些优化(和编译器类似,但不可由开发者直接控制,你写汇编也没用),这方面 x86 不做类似优化
java 和 msvc (仅限编译到 x86 )里的 volatile 关键字除了能保证修改一定反映到内存上以外,也会防止编译器调换前后的读写顺序,以及放置内存栅栏
但其他平台和编译器就没做这个了
然后如果用了锁,不管什么平台还是语言,都会放内存屏障,所以肯定是能保证顺序的
go 里 channel 也起到类似作用,写入 channel 时会保证所有之前发生的副作用都确实已经发生了;同理从 channel 中取值也会保证所有后续操作和副作用都不会在之前运行
这里和缓存毫无关系,事实上 mesi 协议就是为了确保缓存对开发者不可见,而实际上也确实做到了这个目标(除了性能上的差异外无法观测到影响)
在多线程问题上讨论 mesi 根本毫无意义
channel 这里就用作读写屏障了
1 ... 3  4  5  6  7  8  9  10  11  12 ... 125  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2445 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 30ms · UTC 14:41 · PVG 22:41 · LAX 07:41 · JFK 10:41
Developed with CodeLauncher
♥ Do have faith in what you're doing.