一 為什么需要多線程控制
看代碼:
package mutithread;public class ThreadTest { PRivate static int count=0; public static void addCount(){ for(int i=0;i<100;i++){ ++count; } } public static void main(String[] args){ for(int i=0;i<10;i++){ new Thread(new Runnable() { public void run() { addCount(); System.out.println("name="+Thread.currentThread().getName()+";count="+count); } }).start(); } System.out.println("name="+Thread.currentThread().getName()+";count="+count); }}輸出結(jié)果為:name=main;count=0name=Thread-1;count=100name=Thread-5;count=200name=Thread-9;count=300name=Thread-3;count=400name=Thread-7;count=500name=Thread-0;count=700name=Thread-4;count=700name=Thread-8;count=800name=Thread-2;count=900name=Thread-6;count=1000
疑似一切正常,唯一可疑的一點是main線程居然最先結(jié)束了,所以讓main線程先sleep()一下,等待其它線程執(zhí)行完,同時其它線程也sleep()一下,目的是為了加大錯誤發(fā)生的概率,從而說明多線程下上述代碼有問題,需要控制:
public static void main(String[] args) throws InterruptedException{ for(int i=0;i<10;i++){ new Thread(new Runnable() { public void run() { try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } addCount(); System.out.println("name="+Thread.currentThread().getName()+";count="+count); } }).start(); } Thread.sleep(2000); System.out.println("name="+Thread.currentThread().getName()+";count="+count); }輸出如下:name=Thread-3;count=104name=Thread-6;count=204name=Thread-7;count=304name=Thread-0;count=404name=Thread-4;count=504name=Thread-8;count=604name=Thread-2;count=104name=Thread-1;count=704name=Thread-5;count=904name=Thread-9;count=904name=main;count=904
怪異的事情發(fā)生了,都是并發(fā)惹得禍,出錯的原因是多個線程共享count變量。
二 如何解決上述問題java提供了多種措施,最簡單的方式使在操作共享變量的方法上加synchronized關(guān)鍵字:
public static synchronized void addCount(){ for(int i=0;i<100;i++){ ++count; } }然后不管你如何執(zhí)行,最后count值都為1000。三 synchronized關(guān)鍵字是如何做到的見下一篇博客。
四 共享變量是如何被使用的分析JVM內(nèi)存模型可知,每個線程有自己的工作區(qū),對于共享變量,線程每次讀取的是工作內(nèi)存中共享變量的副本,寫入的時候也直接修改工作內(nèi)存中副本的值,然后在某個時間點上再將工作內(nèi)存與主內(nèi)存中的值進行同步。于是,問題來了:如果線程1對某個變量進行了修改,線程2卻不知道。然后又各自將修改后的副本值同步到主內(nèi)存,必然就出錯了。
新聞熱點
疑難解答