在并发编程中,更新多个字段是一个普遍的需求。
例如,有一个结构,其中包含两个字段。LET的更新然后更新,这是两个步骤,但是我们必须确保原子能。
可能有奇怪的孩子的鞋子。为什么需要确保原子质?
让我们从示例程序开始。公共内存被简化为全局变量,将更新10个CO发行。您猜测最终结果是什么?
结果是什么?你能猜出吗?
可能是这样:
也可能是:
根据布置组合,有10*10个结果。
我们想要什么结果?我们希望姓名和年龄匹配,而且我们不能正确。换句话说,名称和年龄的更新必须具有原子操作,并且必须没有定义的状态。
我们想要的是(没有人:我,我)。正确的结果只能出现在下面的10个指定结果中:
这只是一个简单的例子。儿童鞋子应该考虑他们的实际需求,这应该很普遍。
现在有两个问题:
第一个问题:此演示观察运行时间,并利用时间观察。时间约为200毫秒。为什么?
以上是203毫秒。位置:每个人都应该记住这次,这有助于我们的分析。
这200毫秒是因为故意添加了Qi的功能稍微延迟,这可能会使该程序估计较慢。
每个Coroutine都需要至少200毫秒,10个Coroutines一起运行,没有任何相互排斥,重叠的时间,因此整个程序的时间并不全部约200毫秒。
第二个问题:如何解决此正确性的问题。
大约两种方法:
让我们分析以下相同的优势和缺点。
在并发的背景下,使用锁相互排除,这是最常见的想法。锁可以形成关键区域。锁定中的一系列操作只能随时更新,以免更新混淆,从而确保多步操作的原子性。
首先与变量合作,对应于相互排斥的锁:
锁中更新逻辑:
更改上述程序后,是否正确的逻辑是正确的。
但是您注意到另一个可怕的问题吗?
该程序正在缓慢运行!交叉启动开始
同样,使用命令运行程序运行时间,每次延迟增加了延迟增加10倍。
我不禁问自己,为什么?
我仍然记得上面提到的,固定的更新是200毫秒。
锁定后,功能逻辑全部都在锁中,并且10个Coroutine运行功能很复杂。但是,由于锁的相互排除,它被阻塞并等待锁定以确保内部逻辑的序列化。
第一个Coroutine Plus锁,后9必须等待,按顺序推动。最长的等待时间应为1.8秒。
换句话说,程序已执行10次,并累积了时间。该过程在2秒内延迟。
锁并不害怕,锁很糟糕。当大量并发时,由于相互排斥的特征,这里的性能可能会令人担忧。
锁定也失败了。有必要直接进行调度,直到下次唤醒。这里也是Coroutine计划的开销,并且可能的性能较慢。
思考:保证锁后的正确性,并且某些场景性能可能令人担忧。
在此示例中,下一个进化是:原子操作。
善良的提示:
害怕对儿童鞋的误解,宣称锁不可用,他们必须区分场景,如果没有场景的性能优化措施,这是毫无意义的。大多数场景都没有锁的问题。在阅读和写作锁时,更新锁,仅阅读操作并阅读锁。这确实可以带来更大的性能改善,尤其是在写作少时。
实际上,让我们再次深入研究,这本质上是确保更新名称和年龄的原子质,并确保它们支持。实际上,您可以首先在本地环境中设置人的结构,然后分配一个GO提供了这种类型的全局变量的原子值。
如何改变它?
首先设置并发更新的目标:
然后将函数转换为结构的第一部分,然后转换为分配原子的方法:
最后,该功能读取全局变量打印的位置,并且需要使用原子方法:
p.name =没有人:2
P.Age = 30这解决了并发更新的正确问题。感兴趣的儿童鞋可以运行,结果是正确的(没有人:i,i)。
让我们看一下程序的运行时间:
事实证明,它是200毫秒,比实施锁的实施少10倍,并保证了正确性。
为什么是这样?
因为这10个旋ou仍然是并发的,所以没有类似的操作类似于锁定的等待,只有最后一个呼叫才能与状态同步,这次是最小的,因此10个coroutines的运行时间已重叠,自然整个整个整个整个过程的时间。该程序仅为200毫秒。
锁和原子变量都可以确保正确的逻辑。在我们的简短场景中,我相信您感觉到性能之间的差距。
当然,相同的句子,特定的实现取决于特定场景,不能概括。此外,锁定其自身的不可替代效果,它可以确保多个步骤的原子性,而不仅仅是该领域的分配。
我相信你很好奇。以下简短的分析原则真的很神秘吗?
原则可能令人惊讶。
尽管我们现在不了解内部原则,但首先考虑一个问题(否则以后会理解它会很无聊)?
和谐用于分配和获得价值。我的问题是,这两个功能中是否有任何用户数据副本?是否保证了多场副本的原子质?
事先披露:事实并非如此。
对文件的定义,结构本身非常简单,即一个空接口:
在上一篇文章中,Qi Yan具有一个空的界面类型,该类型在GO中实现了共享的GO(),称为结构体():::::
它用于内部使用的程序APE。同一件事位于不同级别。请首先记住,因为此功能用于定义结构。
重点:这三个结构是完全一致的,但是这个地方是不同的,并且本质上没有差异。这为强制性转换类型创造了先决条件。
看一下简短的代码。这是一个简单的循环:
有几点可以解释:
这里有惊喜吗?
内部不是原子副本群!交点引导,结构指针在其中得到处理。仅通过确保指针的原子分配操作。
哦,我的上帝?是吗?原子能在哪里。
核心是:参数必须是局部变量(或新内存)。
以上问题在这里回答:商店,是否有数据副本?
要点:否!没有移动数据
事实证明你是这样的!
回想一下上面的功能确实是局部变量,一个新的内存块:
还有另一个问题,您可能会认为,如果不是指针,而是一个结构?
事情会这样:
再三思:既然是指针的操作,为什么有循环还是一个?
这是因为两个字段的结构。分配初始分配时,应分配类型和数据指针。
它服务于所有类型,此类需求,一般包装。
如果您有任何写作,请阅读,请查看阅读的简要实现:
哇,这太简单了。初始分配的判断(返回零),后面的基础知识基本上仅依赖于函数来读取指针值。
老实说,这个原则使我感到惊讶,当然,让我们避免坑。
作者:Qiyun云存储