天天看點

C#與JAVA線程間同步實作比較

    C#與JAVA二者是對标下的産物,無論設計思想還是文法格式都非常相似,相恨相殺一路走來各自擁有一群擁趸,思想理念都傳承自面向對象的C++,不過要說血緣關系還是C#更近一些,保留了比較多的C++的影子讓人多了幾分熟悉的味道,IDE上VS也比MyEclipse使用者體驗好很多,不用idea去比明顯偏心眼VS,好吧你說對了。

    C#和C++都提供了良好完備的線程間同步機制,C#保留了更多的C++烙印,JAVA則幹練的多讓開發者省心不少。過去在面向過程的程式設計思路上,鎖的操作基本都是基于語句的,鎖的範圍從加鎖開始到解鎖終止,代碼編寫的過程中各種小心鎖區間的邏輯處理,一個異常就可能導緻萬劫不複的死鎖。C#和JAVA把更多面向底層的鎖操作封裝起來,通過賦予對象執行個體一個修飾詞的方法,極大的簡化了步驟,當然也可以對語句塊加鎖,省略了顯式的繁瑣操作。

C# JAVA C++
擷取

Monitor.Enter(object);

Monitor.TryEnter(object);

休眠 Monitor.Wait(object); final void wait();

pthread_cond_wait(_cond, _mutex);

pthread_cond_timewait(_cond, _mutex, _abstime);

喚醒

Monitor.Pulse(object);

Monitor.PulseAll(object);

final void notify();

final void notifyAll();

pthread_cond_signal(_cond);

pthread_cond_broadcast (_cond);

釋放 Monitor.Exit(object);

    上表顯示了C#和JAVA語言基于螢幕的同步方法的函數,C#比JAVA多了對螢幕的擷取和釋放操作,二者都提供休眠等待時間,喚醒操作都提供單點傳播和多點傳播兩種方式,在明确被喚醒對象且預知其執行方法及結果的前提下建議單點傳播方式喚醒,否則多點傳播喚醒後再逐個投入睡眠導緻的驚群上下文切換會造成比較大的系統開銷。需要特别注意的地方是按照甲骨文的推薦把wait()方法放到一個循環中可以有效避免假喚醒(spurious wakeup)情況的發生,雖然Oralce強調這種情況發生的機率極小,其實意思是說:我可告訴你,不聽是你的事情,出了問題别找我。表中用C++做陪襯說明是為了更好的比較這種機制的适用場景,那就是并不是簡單的粗暴加鎖解鎖,而是有條件有尺度的以最小開銷擷取獨占操作。

public void CSharpFunc(int v)
{
	Monitor.Enter(this);
	if (flag)
	{
		try
		{
			Monitor.Wait(this);
		}
		catch(SynchironizationLockException e)
		{
			Console.WriteLine(e);
		}
	}
	Console.Write("Value {0}", v);
	flag = true;
	Monitor.Pulse(this);
	Monitor.Exit(this);
}

synchronized void JavaFunc(int v) {
	while (!flag)
		try {
			wait();
		} catch(InterruptedException e) {
			System.out.println("InterruptedException caught");
		}
	System.out.println("Valuse: " + v);
	flag = false;
	notify();
}           

    前幾天出門體驗了一次7号共享電單車,以為無樁的可以為所欲為騎行,結果沖了押金又充值,掃碼開鎖竟然要指定目的地,因為目的地周邊沒有停車場,隻好騎到地鐵站再換乘,這叫啥事呀,賬上趴着充值剩餘的金額,提不出來也不知道下次啥時候消費,有種上當受騙的感覺,有樁的共享出行交通工具都是反人類設計,改改吧。