3 回答
TA贡献1816条经验 获得超6个赞
当两个或多个线程可以访问共享数据并且他们尝试同时更改它时,会发生竞争条件。因为线程调度算法可以在任何时间在线程之间交换,所以您不知道线程将尝试访问共享数据的顺序。因此,数据变化的结果取决于线程调度算法,即两个线程都“竞相”访问/改变数据。
当一个线程执行“check-then-act”时(例如,“检查”,如果值为X,然后“执行”以执行取决于值为X的操作)并且另一个线程对该值执行某些操作时,通常会出现问题在“检查”和“行为”之间。例如:
if (x == 5) // The "Check"{ y = x * 2; // The "Act" // If another thread changed x in between "if (x == 5)" and "y = x * 2" above, // y will not be equal to 10.}
关键是,y可以是10,或者它可以是任何东西,这取决于另一个线程是否在检查和行为之间改变了x。你没有真正的认识方式。
为了防止发生竞争条件,您通常会锁定共享数据,以确保一次只能有一个线程访问数据。这意味着这样的事情:
// Obtain lock for xif (x == 5){ y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10}// release lock for x
TA贡献1793条经验 获得超6个赞
当访问共享资源的多线程(或其他并行)代码可能以导致意外结果的方式执行时,存在“竞争条件”。
举个例子:
for ( int i = 0; i < 10000000; i++ ){ x = x + 1; }
如果您有5个线程同时执行此代码,则x WOULD NOT的值最终为50,000,000。事实上,每次运行都会有所不同。
这是因为,为了使每个线程增加x的值,它们必须执行以下操作:(简化,显然)
检索x的值将1添加到此值将此值存储到x
任何线程都可以随时处于此过程的任何步骤,并且当涉及共享资源时,它们可以相互踩踏。在读取x和写回x之间的时间内,x的状态可以由另一个线程改变。
假设一个线程检索x的值,但尚未存储它。另一个线程也可以检索相同的x值(因为还没有线程改变它),然后它们都将相同的值(x + 1)存储回x!
例:
线程1:读取x,值为7线程1:将x加1,值现为8线程2:读取x,值为7线程1:在x中存储8线程2:将x加1,值现为8线程2:在x中存储8
通过在访问共享资源的代码之前使用某种锁定机制可以避免竞争条件:
for ( int i = 0; i < 10000000; i++ ){ //lock x x = x + 1; //unlock x}
在这里,答案每次都是50,000,000。
添加回答
举报