亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: 關(guān)于Java 線程的一個問題 [打印本頁]

作者: newcih    時間: 2016-07-16 08:37
標(biāo)題: 關(guān)于Java 線程的一個問題
前幾天,在敲到一個代碼,碰到如下情況:
  1.         @Override
  2.                 public void run()
  3.                 {
  4.                         while(true)       
  5.                         {
  6. // 注釋句在此                        System.out.println(flag);
  7.                                         if (flag)       
  8.                                         {
  9.                                                 System.out.println("flag is true");       
  10.                                                 // 當(dāng)標(biāo)識位為true時,執(zhí)行到這里,轉(zhuǎn)為false
  11.                                                 flag = false;
  12.                                         }
  13.                         }
  14.                 }
復(fù)制代碼
情況是,我在外部改變flag的值,每隔0.5秒就在外部將flag設(shè)置為true。結(jié)果這段代碼中注釋句去掉注釋的話,會有"flag is true"的輸出,但是注釋加上的話,就永遠(yuǎn)不會輸出"flag is true"
有誰可以給出個合理解釋嗎?

全部代碼如下:

  1. class MyThread extends Thread
  2. {
  3.         // 設(shè)置標(biāo)識位
  4.         private boolean flag = false;
  5.         public void setFlag()
  6.         {
  7.                 flag = true;       
  8.         }
  9.         // 線程執(zhí)行
  10.         @Override
  11.                 public void run()
  12.                 {
  13.                         while(true)       
  14.                         {
  15. //                                        System.out.println(flag);
  16.                                         if (flag)       
  17.                                         {
  18.                                                 System.out.println("flag is true");       
  19.                                                 // 當(dāng)標(biāo)識位為true時,執(zhí)行到這里,轉(zhuǎn)為false
  20.                                                 flag = false;
  21.                                         }
  22.                         }
  23.                 }

  24.         public static void main(String[] args)
  25.         {
  26.                 MyThread t = new MyThread();
  27.                 t.start();
  28.                 // 每隔0.5秒設(shè)置標(biāo)識位為true
  29.                 while (true)
  30.                 {
  31.                         try{
  32.                                 Thread.sleep(500);       
  33.                         } catch (InterruptedException e)       
  34.                         {}

  35.                         t.setFlag();
  36.                 }
  37.         }
  38. }
復(fù)制代碼

作者: jeppeter    時間: 2016-07-18 12:38
本帖最后由 jeppeter 于 2016-07-18 12:42 編輯

我只修改了一個地方就可以使你的代碼運行成功了。
  1. public class MyThread extends Thread {
  2.     [color=Red]private volatile boolean flag = false;[/color]
  3.     public void setFlag() {
  4.         flag = true;
  5.     }
  6.     // 線程執(zhí)行
  7.     @Override
  8.     public void run() {
  9.         while (true) {
  10.             if (flag) {
  11.                 System.out.println("flag is true");
  12.                 flag = false;
  13.             }
  14.         }
  15.     }

  16.     public static void main(String[] args) {
  17.         MyThread t = new MyThread();
  18.         t.start();
  19.         while (true) {
  20.             try {
  21.                 Thread.sleep(500);
  22.             } catch (InterruptedException e)
  23.             {}

  24.             t.setFlag();
  25.         }
  26.     }
  27. }
復(fù)制代碼

作者: jeppeter    時間: 2016-07-18 12:41
本帖最后由 jeppeter 于 2016-07-18 12:43 編輯

我只修改了一個地方就可以使你的代碼運行成功了,就是flag添加了volatile屬性。
  1. public class MyThread extends Thread {
  2.     private volatile boolean flag = false;
  3.     public void setFlag() {
  4.         flag = true;
  5.     }
  6.     // 線程執(zhí)行
  7.     @Override
  8.     public void run() {
  9.         while (true) {
  10.             if (flag) {
  11.                 System.out.println("flag is true");
  12.                 flag = false;
  13.             }
  14.         }
  15.     }

  16.     public static void main(String[] args) {
  17.         MyThread t = new MyThread();
  18.         t.start();
  19.         while (true) {
  20.             try {
  21.                 Thread.sleep(500);
  22.             } catch (InterruptedException e)
  23.             {}

  24.             t.setFlag();
  25.         }
  26.     }
  27. }
復(fù)制代碼

作者: arch_yzs    時間: 2016-11-27 16:14
上面的代碼 是不具備線程安全性的.  "結(jié)果這段代碼中注釋句去掉注釋的話,會有"flag is true"的輸出,但是注釋加上的話,就永遠(yuǎn)不會輸出"flag is true" "
你看到的這個輸出結(jié)果是不可控的, 這里一共有兩個線程 : 1 main方法, 2 t.start()
兩個線程可以同時操作 對象t的 flag屬性, 有可能main方法剛剛調(diào)用完 t.setFlag()方法 第二個線程就執(zhí)行了 flag = false , 而main方法中的第二次循環(huán)還沒有來得及第二次調(diào)用setFlag()方法 . t.start()線程的第二次循環(huán)就已經(jīng)執(zhí)行到了if(flag),而此時 flag = false. 所以不輸出 flag is true. (跟你睡眠0.5秒與否關(guān)系不大,只是不睡眠,打印flag is true的可能性會比較大)
輸出結(jié)果會受 兩個線程的執(zhí)行進度影響, 而我們幾乎無法控制這兩個線程的執(zhí)行進度,即使你對線程設(shè)定了執(zhí)行優(yōu)先級. 所以最后的輸出結(jié)果是完全不可預(yù)期的,你看到的結(jié)果只是一個現(xiàn)象,可能同樣的代碼你放到不同的機器上結(jié)果又會不同.跟你的注釋句也沒什么關(guān)系. 至于你問為什么會看到這樣的輸出結(jié)果, 只能說 不可控 什么輸出結(jié)果都有可能.
所以最好使用synchronized來控制線程同步,保證某些代碼不會被 不同線程同時執(zhí)行, 比如這里 對flag值的操作




歡迎光臨 Chinaunix (http://www.72891.cn/) Powered by Discuz! X3.2