简体   繁体   English

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

[英]new to java/android - understanding thread inconsistent state

I was going through this tutorial and it mentioned that an "inconsistent state" will happen if we do not synchronize these 2 lines of code. 我正在阅读本教程并提到如果我们不同步这两行代码就会发生“不一致状态”。 I tried to reproduce this "inconsistent state" but I was not able to do so. 我试图重现这种“不一致的状态”,但我无法这样做。 Can you tell me exactly what is a "inconsistent state" ? 你能告诉我究竟什么是“不一致的状态”吗?

The tutorial stated, "the value of myColorInt won't match the value of myColorName".. but I did not seem to have any problem... can you explain what exactly is the problem they are trying to avoid? 教程说,“myColorInt的值与myColorName的值不匹配”..但我似乎没有任何问题...你能解释他们试图避免的问题究竟是什么?

The situation that is trying to be avoided is known as a race condition : 试图避免的情况被称为竞争条件

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

The result of the sequence 序列的结果

int myColorInt = color.getRGB();      //Statement 1
String myColorName = color.getName(); //Statement 2

depends on the timing with respect to this thread of code executing in other threads. 取决于在其他线程中执行的此代码线程的时序 If another thread sets the color in between these two statements, then the name stored in myColorName won't match the color stored in myColorInt . 如果另一个线程设置在这两个语句之间的颜色,然后存储在名称myColorName将不匹配存储在颜色myColorInt This is what the tutorial means by inconsistent state . 这是教程意味着不一致的状态

Synchronization is used to make certain guarantees about how mutable data is shared and accessible across threads. 同步用于对跨线程共享和访问可变数据的方式提供某些保证。 This block 这个块

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

uses synchronization to make sure the two statements are executed atomically ; 使用同步来确保两个语句以原子方式执行; that is to say, to prevent another thread from changing the state of the color object while this thread is between the two statements (presuming that other threads are also using synchronization properly). 也就是说,防止另一个线程在这个线程位于两个语句之间时改变color对象的状态(假设其他线程也正在使用同步)。

Concurrency and thread safety can be challenging to get correct, even for experts. 即使对于专家来说,并发性和线程安全性也很难实现。 Concurrency issues result in hard to diagnose, hard to reproduce, and sporadic problems. 并发问题导致难以诊断,难以重现和零星的问题。 Since you're just starting out, I recommend avoiding concurrent programming for the time being if possible. 由于您刚刚开始,我建议尽可能避免并发编程。 Otherwise, the book Java Concurrency in Practice by Brian Goetz, et. 否则,Brian Goetz等人的Java Concurrency in Practice一书。 al. 人。 is an excellent start. 是一个很好的开始。

Just because you don't see this problem doesn't mean it won't occur. 仅仅因为你没有看到这个问题并不意味着它不会发生。 However, it MIGHT occur and probably WILL occur at some point. 但是,它可能会发生,并可能会在某些时候发生。 This essentially means there is no guarantee about the outcome of these threads running, and without a guarantee you can't be sure what your code will do. 这实际上意味着无法保证这些线程运行的结果,并且没有保证您无法确定您的代码将执行什么操作。 Solution is to put it in a synchronized block 解决方案是将其置于synchronized块中

I suppose you mean this lines from the site you linked to, that could cause an "inconsistent state" if you omit the synchronization: 我想你的意思是你链接到的网站的这一行,如果省略同步,可能会导致“不一致的状态”:

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

Please note that both methods getRGB() and getName() are declared as synchronized and that the set(…) method also contains a synchronized block. 请注意,两个方法getRGB()getName()都声明为synchronized ,并且set(…)方法也包含synchronized块。


Now imagine this scenario: Let us forget all this synchronized blocks, ie let us see what could happen, if they would not be there. 现在想象一下这个场景:让我们忘记所有这些synchronized块,即让我们看看会发生什么,如果他们不在那里。 We have two threads A and B. 我们有两个线程A和B.

Thread A wants to execute the following statements: 线程A想要执行以下语句:

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

Thread B wants to execute the same, but with the color white: 线程B想要执行相同的操作,但颜色为白色:

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

If all goes well, colorIntA is 0, colorNameA is "Black", colorIntB is 16777215 and colorNameB is "White". 如果一切顺利, colorIntA为0, colorNameA为“Black”, colorIntB为16777215,colorNameB为“White”。

Now let's say the scheduler decides to interrupt execution of thread A after executing getRGB() but before getName() . 现在让我们说调度程序决定执行getRGB() getName() 之前中断线程A的执行。 In the meantime all of threadB runs. 同时所有的threadB运行。 So the whole execution looks like this: 所以整个执行看起来像这样:

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();

Now all is well with colorIntB and colorNameB but the variables of thread A are inconsistent: colorIntA is 0 (as expected) but colorNameA is "White"! 现在一切都很好用colorIntBcolorNameB但是线程A的变量是不一致的: colorIntA是0(如预期的那样)但colorNameA是“白色”! This is the inconsistency the tutorial talks about. 这是教程谈论的不一致。

Using the synchronized blocks avoids this so called race condition by not allowing thread B to work with color until thread A is done with it, ie thread B has to wait until the synchronized block from thread A is finished completely. 使用synchronized块避免了这种所谓的竞争条件 ,因为在线程A完成之前不允许线程B使用color ,即线程B必须等到线程A的synchronized块完全完成。


You might be able to see the problem in action when you put something like the following between getRGB() and getName() , which causes a random wait between 0 and 5 seconds: 当您在getRGB()getName()之间放置类似下面的内容时,您可能会看到问题在于,这会导致0到5秒之间的随机等待:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM