簡體   English   中英

新的java / android - 了解線程不一致的狀態

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

我正在閱讀本教程並提到如果我們不同步這兩行代碼就會發生“不一致狀態”。 我試圖重現這種“不一致的狀態”,但我無法這樣做。 你能告訴我究竟什么是“不一致的狀態”嗎?

教程說,“myColorInt的值與myColorName的值不匹配”..但我似乎沒有任何問題...你能解釋他們試圖避免的問題究竟是什么?

試圖避免的情況被稱為競爭條件

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

序列的結果

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

取決於在其他線程中執行的此代碼線程的時序 如果另一個線程設置在這兩個語句之間的顏色,然后存儲在名稱myColorName將不匹配存儲在顏色myColorInt 這是教程意味着不一致的狀態

同步用於對跨線程共享和訪問可變數據的方式提供某些保證。 這個塊

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

使用同步來確保兩個語句以原子方式執行; 也就是說,防止另一個線程在這個線程位於兩個語句之間時改變color對象的狀態(假設其他線程也正在使用同步)。

即使對於專家來說,並發性和線程安全性也很難實現。 並發問題導致難以診斷,難以重現和零星的問題。 由於您剛剛開始,我建議盡可能避免並發編程。 否則,Brian Goetz等人的Java Concurrency in Practice一書。 人。 是一個很好的開始。

僅僅因為你沒有看到這個問題並不意味着它不會發生。 但是,它可能會發生,並可能會在某些時候發生。 這實際上意味着無法保證這些線程運行的結果,並且沒有保證您無法確定您的代碼將執行什么操作。 解決方案是將其置於synchronized塊中

我想你的意思是你鏈接到的網站的這一行,如果省略同步,可能會導致“不一致的狀態”:

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為“Black”, colorIntB為16777215,colorNameB為“White”。

現在讓我們說調度程序決定執行getRGB() getName() 之前中斷線程A的執行。 同時所有的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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM