0x00 線程調(diào)度
線程調(diào)度指的是系統(tǒng)為線程分配CPU使用權(quán)。分為兩種:
- 協(xié)同式線程調(diào)度
線程想用CPU多久就用多久,用完了才讓給別的線程。實(shí)現(xiàn)簡(jiǎn)單,但容易發(fā)生進(jìn)程阻塞。 - 搶占式線程調(diào)度
可以用yield()讓出使用權(quán)。并且可以設(shè)優(yōu)先級(jí)。即便一個(gè)線程阻塞了,也不會(huì)導(dǎo)致進(jìn)程阻塞。
0x01 (對(duì)象的)線程安全
指的是并發(fā)訪問(wèn)對(duì)象時(shí)不會(huì)進(jìn)行額外的同步操作。比如Immutable的對(duì)象就是線程安全的。
0x02 線程安全的實(shí)現(xiàn)方法
1. 互斥同步(Mutual Exclusion & Synchronization)
又稱阻塞同步。
同步是指多個(gè)線程并發(fā)訪問(wèn)共享數(shù)據(jù)時(shí),保證同一時(shí)刻共享數(shù)據(jù)只被一個(gè)(使用信號(hào)量時(shí)對(duì)應(yīng):一些)線程使用。
互斥是手段,同步是目的。
在Java中,最基本的互斥同步手段就是synchronized關(guān)鍵字(除了synchronized之外,還可以使用ReentrentLock,重入鎖)。
synchronized關(guān)鍵字在編譯后會(huì)行程moniterenter和moniterexit兩個(gè)字節(jié)碼指令,這兩個(gè)指令需要一個(gè)reference類型的參數(shù)來(lái)指明要加鎖和解鎖的對(duì)象。如果synchronized明確指定了對(duì)象參數(shù),就用這個(gè)對(duì)象作為鎖對(duì)象(所以會(huì)看到聲明一個(gè)成員變量的數(shù)組作為鎖對(duì)象);如果沒(méi)有明確指定,就根據(jù)synchronized修飾的是實(shí)例方法還是類方法,取對(duì)應(yīng)的對(duì)象實(shí)例或者Class對(duì)象作為鎖對(duì)象。

在Java中,每個(gè)class都有一個(gè)相應(yīng)的Class對(duì)象。也就是說(shuō),當(dāng)我們編寫(xiě)一個(gè)類,編譯完成后,在生成的.class文件中,就會(huì)產(chǎn)生一個(gè)Class對(duì)象,用于表示這個(gè)類的類型信息。
注意:
synchronized是一個(gè)重量級(jí)(heavyweight)的操作。
Java的線程是映射到操作系統(tǒng)的原生線程上的,阻塞或喚醒線程都需要CPU時(shí)間,幫助用戶態(tài)和內(nèi)核態(tài)之間轉(zhuǎn)換,對(duì)于簡(jiǎn)單的同步塊,有可能狀態(tài)轉(zhuǎn)換的時(shí)間比執(zhí)行的時(shí)間還長(zhǎng)。
0x02 非阻塞同步
從處理問(wèn)題的方式上說(shuō),互斥同步屬于一種悲觀的并發(fā)策略。
隨著硬件指令集的發(fā)展,我們有了另外一個(gè)選擇:基于沖突檢測(cè)的樂(lè)觀并發(fā)策略,通俗地說(shuō),就是先進(jìn)行操作,如果沒(méi)有其他線程爭(zhēng)用共享數(shù)據(jù),那操作就成功了;
如果共享數(shù)據(jù)有爭(zhēng)用,產(chǎn)生了沖突,那就再采取其他的補(bǔ)償措施(最常見(jiàn)的補(bǔ)償措施就是不斷地重試,直到成功為止),這種樂(lè)觀的并發(fā)策略的許多實(shí)現(xiàn)都不需要把線程掛起,因此這種同步操作稱為非阻塞同步(Non-Blocking Synchronization)。
Ref:
http://blog.csdn.net/truelove12358/article/details/54963791
http://blog.csdn.net/qinjienj/article/details/7578582