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

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 23142 | 回復: 4
打印 上一主題 下一主題

關于Java 線程的一個問題 [復制鏈接]

論壇徽章:
0
跳轉到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2016-07-16 08:37 |只看該作者 |倒序瀏覽
前幾天,在敲到一個代碼,碰到如下情況:
  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.                                                 // 當標識位為true時,執(zhí)行到這里,轉為false
  11.                                                 flag = false;
  12.                                         }
  13.                         }
  14.                 }
復制代碼
情況是,我在外部改變flag的值,每隔0.5秒就在外部將flag設置為true。結果這段代碼中注釋句去掉注釋的話,會有"flag is true"的輸出,但是注釋加上的話,就永遠不會輸出"flag is true"
有誰可以給出個合理解釋嗎?

全部代碼如下:

  1. class MyThread extends Thread
  2. {
  3.         // 設置標識位
  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.                                                 // 當標識位為true時,執(zhí)行到這里,轉為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秒設置標識位為true
  29.                 while (true)
  30.                 {
  31.                         try{
  32.                                 Thread.sleep(500);       
  33.                         } catch (InterruptedException e)       
  34.                         {}

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

論壇徽章:
1
15-16賽季CBA聯(lián)賽之新疆
日期:2017-03-09 12:33:45
2 [報告]
發(fā)表于 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. }
復制代碼

論壇徽章:
1
15-16賽季CBA聯(lián)賽之新疆
日期:2017-03-09 12:33:45
3 [報告]
發(fā)表于 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. }
復制代碼

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

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術有限公司. 版權所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關心和支持過ChinaUnix的朋友們 轉載本站內容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP