新的java / android - 了解线程不一致的状态

时间:2014-04-30 20:45:13

标签: java android multithreading

我正在经历this tutorial并且它提到如果我们不同步这两行代码将会发生“不一致状态”。我试图重现这种“不一致的状态”,但我无法这样做。你能告诉我究竟什么是“不一致的状态”吗?

教程说,“myColorInt的值与myColorName的值不匹配”..但我似乎没有任何问题......你能解释一下他们试图避免的问题究竟是什么? / p>

3 个答案:

答案 0 :(得分:1)

试图避免的情况称为竞争条件

http://en.wikipedia.org/wiki/Race_condition

序列的结果

int myColorInt = color.getRGB();      //Statement 1
String myColorName = color.getName(); //Statement 2
对于在其他线程中执行的此代码线程,

取决于 timing 。如果另一个线程在这两个语句之间设置颜色,则myColorName中存储的名称将与myColorInt中存储的颜色匹配。这就是教程所指的不一致状态

同步用于对跨线程共享和访问可变数据的方式提供某些保证。这个块

synchronized (color) {
    int myColorInt = color.getRGB();
    String myColorName = color.getName();
} 

使用同步来确保两个语句以原子方式执行;也就是说,防止另一个线程在这个线程位于两个语句之间时改变color对象的状态(假设其他线程也正在使用同步)。

即使对于专家来说,并发和线程安全也可能很难实现。并发问题导致难以诊断,难以重现和零星的问题。由于您刚刚开始,我建议尽可能避免并发编程。否则,Brian Goetz等人的书 Java Concurrency in Practice 。人。是一个很好的开始。

答案 1 :(得分:0)

仅仅因为你没有看到这个问题并不意味着它不会发生。但是,它可能会发生,并可能会在某些时候发生。这实际上意味着无法保证这些线程运行的结果,并且没有保证您无法确定您的代码将执行什么操作。解决方案是将其放在synchronized

答案 2 :(得分:0)

我想你的意思是你链接到的网站的这一行,如果省略同步,可能会导致“不一致的状态”:

synchronized (color) {
    int myColorInt = color.getRGB();
    String myColorName = color.getName();
}

请注意,getRGB()getName()两种方法都声明为synchronized,而set(…)方法也包含synchronized块。


现在想象一下这个场景:让我们忘记所有这些synchronized块,即让我们看看会发生什么,如果他们不在那里。我们有两个线程A和B.

线程A想要执行以下语句:

color.set(0, 0, 0, "Black");
int colorIntA = color.getRGB();
String colorNameA = color.getName();

线程B想要执行相同的操作,但颜色为白色:

color.set(255, 255, 255, "White");
int colorIntB = color.getRGB();
String colorNameB = color.getName();

如果一切顺利,colorIntA为0,colorNameA为“黑色”,colorIntB为16777215,colorNameB为“白色”。

现在假设调度程序决定在执行getRGB()之后中断执行线程A 但在 getName()之前执行。同时所有的threadB运行。所以整个执行看起来像这样:

color.set(0, 0, 0, "Black");
int colorIntA = color.getRGB();
// here thread A is interrupted and all of thread B runs
color.set(255, 255, 255, "White");
int colorIntB = color.getRGB();
String colorNameB = color.getName();
// thread B is done, continuing with remaining statement of thread A
String colorNameA = color.getName();

现在colorIntBcolorNameB一切顺利,但线程A的变量不一致:colorIntA为0(如预期的那样),但colorNameA为“白色”!这是教程谈论的不一致。

使用synchronized块避免了这种所谓的竞争条件,因为在线程A完成之前不允许线程B与color一起使用,即线程B必须等到线程A的synchronized块完全结束。


当您在getRGB()getName()之间放置以下类似内容时,您可能会看到问题在于行动,这会导致0到5秒之间的随机等待:

try {
    Thread.sleep((long)(Math.random() * 5000));
} catch (InterruptedException e) {
    // not relevant in this case
}