線程定義
線程(英語(yǔ):thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位溜徙。它被包含在進(jìn)程之中湃缎,是進(jìn)程中的實(shí)際運(yùn)作單位。一條線程指的是進(jìn)程中一個(gè)單一順序的控制流蠢壹,一個(gè)進(jìn)程中可以并發(fā)多個(gè)線程嗓违,每條線程并行執(zhí)行不同的任務(wù)。在Unix System V及SunOS中也被稱為輕量進(jìn)程(lightweight processes)图贸,但輕量進(jìn)程更多指內(nèi)核線程(kernel thread)蹂季,而把用戶線程(user thread)稱為線程。
線程是獨(dú)立調(diào)度和分派的基本單位求妹。線程可以操作系統(tǒng)內(nèi)核調(diào)度的內(nèi)核線程,如Win32線程佳窑;由用戶進(jìn)程自行調(diào)度的用戶線程制恍,如Linux平臺(tái)的POSIX Thread;或者由內(nèi)核與用戶進(jìn)程神凑,如Windows 7的線程净神,進(jìn)行混合調(diào)度。
同一進(jìn)程中的多條線程將共享該進(jìn)程中的全部系統(tǒng)資源溉委,如虛擬地址空間鹃唯,文件描述符和信號(hào)處理等等。但同一進(jìn)程中的多個(gè)線程有各自的調(diào)用棧(call stack)瓣喊,自己的寄存器環(huán)境(register context)坡慌,自己的線程本地存儲(chǔ)(thread-local storage)。
一個(gè)進(jìn)程可以有很多線程藻三,每條線程并行執(zhí)行不同的任務(wù)洪橘。
線程實(shí)現(xiàn)
Java中的線程都是調(diào)用的原生系統(tǒng)的本地函數(shù)跪者,Java線程模型是基于操作系統(tǒng)原生線程模型實(shí)現(xiàn)的,實(shí)現(xiàn)線程有三種方式:內(nèi)核線程實(shí)現(xiàn)熄求、用戶線程實(shí)現(xiàn)渣玲、混合線程實(shí)現(xiàn)。
內(nèi)核線程實(shí)現(xiàn)
直接由操作系統(tǒng)內(nèi)核支持的線程弟晚,通過(guò)內(nèi)核來(lái)完成進(jìn)程切換忘衍。每個(gè)內(nèi)核線程就是一個(gè)內(nèi)核的分身,這樣操作系統(tǒng)就可以同時(shí)處理多件事情卿城,支持多線程的內(nèi)核被稱為多線程內(nèi)核枚钓。
程序一般不直接使用內(nèi)核線程,而是使用一種高級(jí)接口——輕量級(jí)進(jìn)程藻雪,輕量級(jí)進(jìn)程就是我們通常意義上的線程秘噪,可以獲得內(nèi)核線程的支持,與內(nèi)核線程構(gòu)成1:1
的線程模型勉耀。
由于得到內(nèi)核線程的支持指煎,每個(gè)輕量級(jí)進(jìn)程都成為一個(gè)獨(dú)立的調(diào)度單元,即時(shí)有一個(gè)輕量級(jí)進(jìn)程在系統(tǒng)調(diào)用中阻塞便斥,也不會(huì)影響整個(gè)進(jìn)程至壤,但也有其局限性:由于是基于內(nèi)核線程實(shí)現(xiàn)的,各種操作枢纠,如創(chuàng)建像街、銷毀及同步,都需要進(jìn)行系統(tǒng)調(diào)用晋渺。而系統(tǒng)調(diào)用代價(jià)較高镰绎,需要在內(nèi)核態(tài)和用戶態(tài)來(lái)回切換。
用戶線程實(shí)現(xiàn)
從廣義上說(shuō)木西,一個(gè)線程不是內(nèi)核線程畴栖,就是用戶線程,所以輕量級(jí)進(jìn)程也屬于用戶線程八千。狹義的用戶線程是指完全建立在用戶空間上的吗讶,系統(tǒng)內(nèi)核不能感知到其存在。
用戶線程的創(chuàng)建恋捆、同步照皆、銷毀和調(diào)度都是在用戶空間實(shí)現(xiàn)的,因此相對(duì)較快沸停,代價(jià)相對(duì)較低膜毁。這種用戶線程和進(jìn)程是N:1
的線程模型。
由于用戶線程沒(méi)有內(nèi)核的支持,線程的創(chuàng)建爽茴、切換和調(diào)度是需要自己實(shí)現(xiàn)的葬凳,而且由于操作系統(tǒng)只把CPU資源分配到進(jìn)程,那諸如“阻塞如何處理”室奏、“多處理器系統(tǒng)中如何將線程映射到其他處理器”這類問(wèn)題解決起來(lái)異常復(fù)雜火焰。
混合實(shí)現(xiàn)
這種實(shí)現(xiàn)模式將內(nèi)核線程與用戶線程一起使用,在這種方式下既存在用戶線程胧沫,也存在輕量級(jí)進(jìn)程昌简。用戶線程還是完全建立在用戶空間,因此用戶線程的創(chuàng)建绒怨、切換等操作依舊低廉纯赎。而操作系統(tǒng)提供的輕量級(jí)進(jìn)程則作為用戶線程和內(nèi)核線程的橋梁,這樣就可以使用內(nèi)核提供的線程調(diào)度及處理器映射南蹂。這種實(shí)現(xiàn)下犬金,用戶線程和輕量級(jí)進(jìn)程是M:N
的模式。
Java線程調(diào)度
線程調(diào)度分為協(xié)同式和搶占式六剥。
-
協(xié)同式調(diào)度
:線程的執(zhí)行時(shí)間由線程自己控制晚顷,這種的實(shí)現(xiàn)很簡(jiǎn)單,但是很可能造成很?chē)?yán)重的后果疗疟。 -
搶占式調(diào)度
:由操作系統(tǒng)分配線程執(zhí)行的時(shí)間该默,線程切換的決定權(quán)在操作系統(tǒng)。
有時(shí)候我們需要為某些線程多分配時(shí)間策彤,這時(shí)我們就需要用到線程優(yōu)先級(jí)的方法栓袖,Java提供了10種優(yōu)先級(jí)。Java優(yōu)先級(jí)是在操作系統(tǒng)的原生線程優(yōu)先級(jí)上實(shí)現(xiàn)的店诗,所以對(duì)于同一個(gè)優(yōu)先級(jí)裹刮,不同的操作系統(tǒng)可能有不同的表現(xiàn),也就是說(shuō) Java線程優(yōu)先級(jí)不是可靠的庞瘸。
Java線程狀態(tài)切換
Java線程模型定義了 6 種狀態(tài)捧弃,在任意一個(gè)時(shí)間點(diǎn),一個(gè)線程有且只有其中一個(gè)狀態(tài):
-
新建(New)
:新建的Thread恕洲,尚未開(kāi)始塔橡。 -
運(yùn)行(Runable)
:包含操作系統(tǒng)線程狀態(tài)中的Running梅割、Ready霜第,也就是處于正在執(zhí)行或正在等待CPU分配時(shí)間的狀態(tài)。 -
無(wú)限期等待(Waiting)
:處于這種狀態(tài)的線程不會(huì)被分配CPU時(shí)間户辞,等待其他線程喚醒泌类。 -
限期等待(Timed Waiting)
:處于這種狀態(tài)的線程不會(huì)被分配CPU時(shí)間,在一定時(shí)間后會(huì)由系統(tǒng)自動(dòng)喚醒。 -
阻塞(Blocked)
:在等待獲得排他鎖刃榨。 -
結(jié)束(Terminated)
:已終止的線程弹砚。
線程安全
多線程訪問(wèn)同一代碼,不會(huì)產(chǎn)生不確定的結(jié)果枢希。