我有一個類如下:爲什麼在使用getter和setter的時候線程不安全的類無法工作?
public class BoolFlag
{
boolean flag;
public BoolFlag()
{
flag=false;
}
public synchronized void setFlag(boolean flag)
{
this.flag=flag;
}
public synchronized boolean getFlag()
{
return flag;
}
}
如果我不設置getter和setter進行同步,這將導致該問題如下:
當我設置稱爲BoolFlag的對象在ImageReady中一個buttonclick listiner:
if (status == JFileChooser.APPROVE_OPTION)
{
try
{
System.out.println("File chosen");
imgFile=chooser.getSelectedFile();
image.setImg(ImageIO.read(imgFile));
imageready.setFlag(true);
}
catch(Exception e)
{
System.out.println("file not opened");
}
}
然後把它在另一個線程:
public void run()
{
boolean running=true;
while(running)
{
// System.out.println("Img sender running");
if(imageready.getFlag())
{ System.out.println("trying to send img");
try
{
OutputStream outputStream = img_s.getOutputStream();
ImageIO.write(image.getImg(), "jpg", outputStream);
System.out.println("Send image"+System.currentTimeMillis());
outputStream.flush();
outputStream.close();
imageready.setFlag(false);
}
catch(Exception e)
{
System.out.println("image client send failed");
imageready.setFlag(false);
}
}
}
}
我期望是選擇文件後,ImageReady的應設置爲true,那麼線程誰得到的標誌執行塊中的語句:
if(imageready.getFlag()){...send image...}
但它不會進入塊中的偶數儘管imageready被設置爲true。
正如你可能會注意到,我有一份聲明被註釋掉,如果塊的前面:
// System.out.println("Img sender running");
如果我不註釋掉,在if塊中的語句將被執行。把其他無關的陳述,如睡眠(100)可能會導致相同的效果。如果我在if(imageready.getflag())處放置一個斷點,然後逐步執行它,它也會進入該塊。
如果我設置getter和setter被同步,這些問題不會發生。 看來這是關於胎面安全類的東西,但我不明白爲什麼它很重要,即使我只是使用getter和setter。
你還可以使用Thread.join – ControlAltDel
對不起,其他? –
在生產者 - 消費者問題中,生產者和消費者會修改同一個對象。但是我的情況有點不同:一個線程正在修改imageready的值,而另一個線程正好修改了它的值。 –