我正在尝试理解多线程,并且对多线程的执行时间如何导致诸如竞争条件之类的问题感到困惑。我最近在一篇文章中读到了这一点:“当你引入多线程的概念时,你就打开了两个线程同时访问/修改内存中同一对象的可能性。”我们所说的“同时”到底是什么意思?这是否意味着一个内存位置可以被多个线程在同一时刻读取例如,两个线程在1.1秒的时候恰好读取了变量a的值?如果是,那么这个来自Java并发的图表实际上是否意味着线程B读取值9比线程A稍微晚一点?我该如何解释它呢?
发布于 2017-07-28 12:05:54
我会尽量简明扼要。
假设你有一些变量存储在地址为0x101010的内存中。假设这个变量是一个计数器,它计算某个函数(X)被调用了多少次。有两个线程(A和B)调用函数X。A调用了X,0.0001毫秒后B也调用了X。假设计数器的初始值是0。则A已在时间0s读取值0,并在时间0.0002毫秒使其递增。因此,在时间0.0002 ms时,值为1。但是,B在时间0.0001ms时已读取此值(0.0001 < 0.0002)。此时计数器仍为零。并且还在0.0003毫秒的时间将其递增到1。最后,计数器值是1,而它应该是2。
发布于 2017-07-28 12:11:59
你应该多读一点。简单地说,假设我们正在使用两个run方法,这两个方法正在访问变量x=5。
方法A将该值写入x=10。
现在方法B将其写入x=15。
现在,如果在一段时间后,方法a需要x的值,它将得到x=15,而不是x=10。因此,两个方法访问的值是相同的。
发布于 2017-07-28 23:13:05
让我从多线程代码是复杂的开始,当你从并行性的角度考虑时,可能会发生许多不同的事情。
竞争条件通常是指并行代码上的一种情况,在这种情况下,根据不同并行执行线程的执行顺序,可以获得不同的结果。“竞争”是指不同的线程“竞争”共享资源,进入终结线的不同顺序产生不同的结果。
你首先要明白的是,现在大多数开发都是通过C#、Java、Golang等所谓的高级语言来完成的。在这些语言中,有一行代码,即使它看起来像一条命令,实际上也被翻译成了多条汇编指令。
这样,当您执行以下最简单的示例时:
value = a + 1;
实际上,在引擎盖下,这被(广泛地)翻译为:
中
理解了这一部分后,您将看到现在当我们说两件事同时执行时,我们指的是更高级别的抽象
如果你想一下我强调的3个步骤,那么从竞态条件的角度考虑会更有意义。如果你回过头来看你发布的图片,序列如下:
< Thread1 >H122发生上下文切换并恢复线程1执行步骤2(使用先前的红色值9)并计算10<代码>H225<代码>H126线程1执行步骤3并将”值“更新为10。<代码>H227F228
最终值为10。
<代码>H140线程2执行步骤2获取刚刚读取的值(10)并计算11<代码>H241线程2执行步骤3并将”值“更新为11<代码>H243<代码>F244
最终值: 11
因此,根据线程的执行顺序,您将获得不同的结果。这就是通常所说的竞态条件。
这一切都非常简单,因为这是一个简单的增量操作。随着代码变得越来越复杂,竞态条件的性质也变得越来越复杂,但事实是,你在高级代码中认为是单个操作的东西,实际上在IL或汇编程序中被编译成了几个操作。
https://stackoverflow.com/questions/45364611
复制相似问题