java多線程訪問同一變量及簡單同步問題(待後續整理)

先貼代碼:

import java.util.Vector;

public class Counter {

	public static int count = 0;
//	synchronized 
	public static void inc() {
		for (int i = 0; i < 1000; i++){
			count++;
		}
		System.out.println(Thread.currentThread().getName() + "----" + count);
	}

	public static void main(String[] args) {
		Vector<Thread> ts = new Vector<Thread>();
		for (int i = 0; i < 200; i++) {
			Thread t = new Thread(new Runnable() {
				@Override
				public void run() {
					Counter.inc();
				}
			});
			ts.add(t);
			t.start();
		}
		for (Thread t : ts) {
			try {
				t.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		System.out.println("----------" + Counter.count);
	}
}

很簡單的邏輯,就是for循環開新的線程然後每個線程執行對static靜態變量count的修改。

在inc()方法中,對count用for循環執行操作很重要。因爲現在的電腦性能都應經很好(一般情況下資源都浪費了),所以如果簡單地執行一次count++的話,又沒有一些線程和它競爭CPU,所以很有可能看不到實驗的結果。(我的機器就是這種情況,找我們項目組的哥問了才瞭解)。

線上一張圖,然後再說:(圖片來自:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html)<----他的這篇文章有問題,可以說代碼根本和他說的對不上,下面再噴他,但是他的分析是對的。


我們的用循環新開的線程肯定不是主線程。所以我們的子線程要去訪問count變量,就是這樣,read -> load -> use -> assign -> store -> write.

read 和load一下子就OK了,但是use,assign,store是對自己現成的這塊內存的操作,是可以進行很多次和需要時間的。

那麼問題容易出現在什麼地方呢,就出在這塊時間上,世界並不是靜止的,計算機也一樣。你操作的這段時間,其他的進程也可以操作(因爲你並沒有加鎖同步)。街上的美女又不是隻有你可以看,對不對。

好了,這就是問題所在。執行這段代碼的時候一個線程拿到了主線程內存中的count的拷貝,然後要進行1000次加操作。可是1000次還沒幹完呢,又來了個線程得到了最新的count的拷貝,也進行1000加操作。但是第二個進程得到的拷貝並不是1000,可能只有209.好了,解釋到這裏就可以了。

然後最後打印出最後的count的值,驗證代碼。

開始噴(輕噴)。上圖的作者的代碼裏面,沒有:

for (Thread t : ts) {
			try {
				t.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

這段代碼,然後就輸出,就說怎麼地怎麼地。問什麼不對很簡單,這段代碼的作用是讓主進程在所有子進程執行完之後執行。如果子進程沒執行完就把半路上的count輸出,效果雖然跟沒同步是一樣的但是絕不是那麼回事。

關於讓主進程在子進程之後執行的方法主要有兩個,以後再說。哦,對了,join()的意思是:“等待該線程執行完之後再執行”,將主語和賓語帶入,就是:“等待我子線程執行完之後你主線程再執行”。

(如果把join用在產生新線程的for循環中的話你會發現線程ID都是排的整整齊齊的呢。。。。爲什麼應該不難理解)

接下來想想,同步的話怎麼搞呢?

synchrinized放在public和static之間就好(這麼詳細我也醉了)。然後運行一下看看,你就懂了。

發佈了27 篇原創文章 · 獲贊 13 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章