亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

詳解Java多線程開發中的數據同步

2024-07-14 08:44:04
字體:
來源:轉載
供稿:網友

  Java中的變量分為兩類:局部變量和類變量。局部變量是指在方法內定義的變量,如在run方法中定義的變量。對于這些變量來說,并不存在線程之間共享的問題。因此,它們不需要進行數據同步。類變量是在類中定義的變量,作用域是整個類。這類變量可以被多個線程共享。因此,我們需要對這類變量進行數據同步。

  數據同步就是指在同一時間,只能由一個線程來訪問被同步的類變量,當前線程訪問完這些變量后,其他線程才能繼續訪問。這里說的訪問是指有寫操作的訪問,如果所有訪問類變量的線程都是讀操作,一般是不需要數據同步的。

  那么如果不對共享的類變量進行數據同步,會發生什么情況呢?讓我們先看看下面的代碼會發生什么樣的事情:

package test;

public class MyThread extends Thread
{
public static int n = 0;

public void run()
{
int m = n;
yield();
m++;
n = m;
}
public static void main(String[] args) throws Exception
{
MyThread myThread = new MyThread ();
Thread threads[] = new Thread[100];
for (int i = 0; i < threads.length; i++)
threads[i] = new Thread(myThread);
for (int i = 0; i < threads.length; i++)
threads[i].start();
for (int i = 0; i < threads.length; i++)
threads[i].join();
System.out.println("n = " + MyThread.n);
}
}

  在執行上面代碼的可能結果如下:

  n = 59

  看到這個結果,可能很多讀者會感到奇怪。這個程序明明是啟動了100個線程,然后每個線程將靜態變量n加1.最后使用join方法使這100個線程都運行完后,再輸出這個n值。按正常來講,結果應該是n = 100??善Y果小于100。

  其實產生這種結果的罪魁禍首就是我們經常提到的“臟數據”。而run方法中的yield()語句就是產生“臟數據”的始作俑者(不加yield語句也可能會產生“臟數據”,但不會這么明顯,只有將100改成更大的數,才會經常產生“臟數據”,在本例中調用yield就是為了放大“臟數據”的效果)。yield方法的作用是使線程暫停,也就是使調用yield方法的線程暫時放棄CPU資源,使CPU有機會來執行其他的線程。為了說明這個程序如何產生“臟數據”,我們假設只創建了兩個線程:thread1和thread2.由于先調用了thread1的start方法,因此,thread1的run方法一般會先運行。當thread1的run方法運行到第一行(int m = n;)時,將n的值賦給m.當執行到第二行的yield方法后,thread1就會暫時停止執行,而當thread1暫停時,thread2獲得了CPU資源后開始運行(之前thread2一直處于就緒狀態),當thread2執行到第一行(int m = n;)時,由于thread1在執行到yield時n仍然是0,因此,thread2中的m獲得的值也是0.這樣就造成了thread1和thread2的m獲得的都是0.在它們執行完yield方法后,都是從0開始加1,因此,無論誰先執行完,最后n的值都是1,只是這個n被thread1和thread2各賦了一遍值。這個過程如下圖如示:

  也許有人會問,如果只有n++,會產生“臟數據”嗎?答案是肯定的。那么n++只是一條語句,又如何在執行過程中將CPU交給其他的線程呢?其實這只是表面現象,n++在被Java編譯器編譯成中間語言(也叫做字節碼)后,并不是一條語言。讓我們看看下面的Java代碼將會被編譯成什么樣的Java中間語言。

  Java源代碼

public void run()
{
n++;
}

被編譯后的中間語言代碼

001  public void run()
002  {
003      aload_0        
004      dup            
005      getfield
006      iconst_1       
007      iadd           
008      putfield      
009      return         
010  }

  大家可以看到在run方法中只有n++一條語句,而在編譯后,卻有7條中間語言語句。我們并不需要知道這些語句的功能是什么,只看一下第005、007和008行語句。在005行是getfield,根據它的英文含義可知是要得到某個值,因為這里只有一個n,所以毫無疑問,是要得到n的值。而在007行的iadd也不難猜測是將這個得到的n值加1.在008行的putfield的含義我想大家可能已經猜出來了,它負責將這個加1后的n再更新回類變量n.說到這,可能大家還有一個疑惑,執行n++時直接將n加1不就行了,為什么要如此費周折。其實這里涉及到一個Java內存模型的問題。

  Java的內存模型分為主存儲區和工作存儲區。主存儲區保存了Java中所有的實例。也就是說,在我們使用new來建立一個對象后,這個對象及它內部的方法、變量等都保存在這一區域,在MyThread類中的n就保存在這個區域。主存儲區可以被所有線程共享。而工作存儲區就是我們前面所講的線程棧,在這個區域里保存了在run方法以及run方法所調用的方法中定義的變量,也就是方法變量。在線程要修改主存儲區中的變量時,并不是直接修改這些變量,而是將它們先復制到當前線程的工作存儲區,在修改完后,再將這個變量值覆蓋主存儲區的相應的變量值。

  在了解了Java的內存模型后,就不難理解為什么n++也不是原子操作了。它必須經過一個拷貝、加1和覆蓋的過程。這個過程和在MyThread類中模擬的過程類似。大家可以想象,如果在執行到getfield時,thread1由于某種原因被中斷,那么就會發生和MyThread類的執行結果類似的情況。要想徹底解決這個問題,就必須使用某種方法對n進行同步,也就是在同一時間只能有一個線程操作n,這也稱為對n的原子操作。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩在线影院| 久久香蕉频线观| 国产精品视频久久| 欧美日韩中文字幕在线视频| 国产91精品久久久久| 色综合老司机第九色激情| 久久免费精品视频| 亚洲国产精品成人一区二区| 欧美国产日韩中文字幕在线| 精品亚洲aⅴ在线观看| 亚洲图片欧美午夜| 高清欧美电影在线| 日韩大片在线观看视频| 国产精品免费一区二区三区都可以| 51ⅴ精品国产91久久久久久| 亚洲欧美中文日韩v在线观看| 国产精品电影久久久久电影网| 一夜七次郎国产精品亚洲| 日韩在线观看精品| www高清在线视频日韩欧美| 亚洲国产精品人人爽夜夜爽| 欧美日韩国产精品| 欧美激情久久久| 日本一区二区三区在线播放| 国产一区二区三区三区在线观看| 精品国产依人香蕉在线精品| 亚洲精品视频播放| 久久精品视频在线观看| 国产精品久久久久久久久影视| 欧美精品在线免费观看| 日韩精品视频在线播放| 国产精品va在线播放我和闺蜜| 精品国偷自产在线| 日韩成人久久久| 久久久在线视频| 中文字幕日韩精品有码视频| 538国产精品一区二区免费视频| 亚洲精品久久久一区二区三区| 亚洲电影免费观看高清完整版在线| 欧美体内谢she精2性欧美| 亚洲精品一区久久久久久| …久久精品99久久香蕉国产| 中文字幕成人在线| 久久成年人免费电影| 欧美午夜xxx| 三级精品视频久久久久| 亚洲a中文字幕| 国产极品精品在线观看| 国产91热爆ts人妖在线| 久久久在线观看| 亚洲少妇中文在线| 久久6精品影院| 久久久久久久香蕉网| 欧美高清在线播放| 欧美视频在线观看免费网址| 日韩免费在线看| 久久成人国产精品| 在线视频亚洲欧美| 国产这里只有精品| 久久久久久亚洲精品中文字幕| 98视频在线噜噜噜国产| 欧美日韩在线另类| 欧美性视频在线| 日韩一区二区三区xxxx| 国产精品欧美一区二区三区奶水| 亚洲九九九在线观看| 日韩欧美在线免费观看| 国产免费亚洲高清| 成人精品在线观看| 亚洲区一区二区| 亚洲www在线观看| 亚洲欧美中文日韩在线| 国产成人久久久精品一区| 色综合久久悠悠| 久久手机免费视频| 久久黄色av网站| 久久免费视频观看| 亚洲第一区在线观看| 精品一区二区三区电影| 国产98色在线| 日韩精品久久久久久久玫瑰园| 欧美极品在线视频| 成人疯狂猛交xxx| 韩国三级电影久久久久久| 中文字幕综合一区| 国产精品香蕉在线观看| 成人网中文字幕| 国产又爽又黄的激情精品视频| 欧美肥臀大乳一区二区免费视频| 欧美大片免费看| 九九热这里只有精品免费看| 国产成人亚洲综合青青| 国产成人精品视频| 成人av色在线观看| 亚洲日本成人网| 日韩欧美大尺度| 国产精品久久久久久久av大片| 亚洲性无码av在线| 韩国精品美女www爽爽爽视频| 久久久精品亚洲| 色www亚洲国产张柏芝| 九九精品在线观看| 国产啪精品视频网站| 91亚洲精品久久久久久久久久久久| 国产视频久久久久久久| 91精品国产综合久久男男| 欧美怡红院视频一区二区三区| 精品视频在线播放| 欧洲亚洲女同hd| 亚洲午夜未满十八勿入免费观看全集| 日韩在线观看免费全| 久久九九国产精品怡红院| 久久久久久久久久国产| 亚洲福利在线观看| 国产精品成人国产乱一区| 欧美成人精品在线观看| 欧美韩国理论所午夜片917电影| 日韩在线视频国产| 91精品国产高清久久久久久| 日韩免费在线视频| 国产精品综合久久久| 最好看的2019的中文字幕视频| 中文国产亚洲喷潮| 欧美精品18videosex性欧美| 中文字幕9999| 亚洲综合国产精品| 欧美另类第一页| 欧美丰满老妇厨房牲生活| 欧美亚洲成人xxx| 日本视频久久久| 亚洲日本成人女熟在线观看| 欧美亚洲国产视频小说| 国产一区二区三区高清在线观看| 日韩av在线播放资源| 国产精品入口免费视频一| 精品国产一区二区三区四区在线观看| 精品偷拍一区二区三区在线看| 欧美福利视频在线观看| 日韩精品亚洲元码| 97色在线播放视频| 欧美高清激情视频| 久久久久久国产免费| 久久国产精品首页| 97国产suv精品一区二区62| 成人国内精品久久久久一区| 欧美电影电视剧在线观看| 久久躁日日躁aaaaxxxx| 91青草视频久久| 中文字幕精品在线视频| 亚洲第一视频网| 亚洲精品免费网站| 久久理论片午夜琪琪电影网| 日本一区二区在线播放| 欧美激情一二区| 国产日韩欧美成人| 欧美激情视频在线观看| 日韩一区在线视频| 亚洲免费高清视频| 欧美精品成人91久久久久久久| 欧美激情一级二级| 久久精品成人欧美大片| 亚洲午夜国产成人av电影男同| 欧美视频第一页| 日韩暖暖在线视频|