Golang 協(xié)程/線程/進(jìn)程 區(qū)別以及 GMP 詳解

Golang 協(xié)程/線程/進(jìn)程 區(qū)別詳解

轉(zhuǎn)載請(qǐng)注明來(lái)源:https://janrs.com/mffp


概念

進(jìn)程 每個(gè)進(jìn)程都有自己的獨(dú)立內(nèi)存空間利职,擁有自己獨(dú)立的地址空間、獨(dú)立的堆和棧植袍,既不共享堆旭愧,亦不共享?xiàng)B拚洹R粋€(gè)程序至少有一個(gè)進(jìn)程勋颖,一個(gè)進(jìn)程至少有一個(gè)線程耘擂。進(jìn)程切換只發(fā)生在內(nèi)核態(tài)摇庙。

線程 線程擁有自己獨(dú)立的棧和共享的堆旱物,共享堆,不共享?xiàng)N捞唬怯刹僮飨到y(tǒng)調(diào)度宵呛,是操作系統(tǒng)調(diào)度(CPU調(diào)度)執(zhí)行的最小單位。對(duì)于進(jìn)程和線程,都是有內(nèi)核進(jìn)行調(diào)度,有 CPU 時(shí)間片的概念, 進(jìn)行搶占式調(diào)度夕凝。內(nèi)核由系統(tǒng)內(nèi)核進(jìn)行調(diào)度, 系統(tǒng)為了實(shí)現(xiàn)并發(fā),會(huì)不斷地切換線程執(zhí)行, 由此會(huì)帶來(lái)線程的上下文切換宝穗。

協(xié)程 協(xié)程線程一樣共享堆,不共享?xiàng)B氡瑓f(xié)程是由程序員在協(xié)程的代碼中顯示調(diào)度逮矛。協(xié)程(用戶態(tài)線程)是對(duì)內(nèi)核透明的, 也就是系統(tǒng)完全不知道有協(xié)程的存在, 完全由用戶自己的程序進(jìn)行調(diào)度。在棧大小分配方便转砖,且每個(gè)協(xié)程占用的默認(rèn)占用內(nèi)存很小须鼎,只有 2kb ,而線程需要 8mb堪藐,相較于線程,因?yàn)閰f(xié)程是對(duì)內(nèi)核透明的莉兰,所以棧空間大小可以按需增大減小礁竞。

并發(fā) 多線程程序在單核上運(yùn)行
并行 多線程程序在多核上運(yùn)行

協(xié)程與線程主要區(qū)別是它將不再被內(nèi)核調(diào)度糖荒,而是交給了程序自己而線程是將自己交給內(nèi)核調(diào)度,所以golang中就會(huì)有調(diào)度器的存在模捂。


詳解

進(jìn)程

在計(jì)算機(jī)中捶朵,單個(gè) CPU 架構(gòu)下,每個(gè) CPU 同時(shí)只能運(yùn)行一個(gè)任務(wù)狂男,也就是同時(shí)只能執(zhí)行一個(gè)計(jì)算综看。如果一個(gè)進(jìn)程跑著,就把唯一一個(gè) CPU 給完全占住岖食,顯然是不合理的红碑。而且很大概率上,CPU 被阻塞了,不是因?yàn)橛?jì)算量大析珊,而是因?yàn)榫W(wǎng)絡(luò)阻塞羡鸥。如果此時(shí) CPU 一直被阻塞著,其他進(jìn)程無(wú)法使用忠寻,那么計(jì)算機(jī)資源就是浪費(fèi)了惧浴。
這就出現(xiàn)了多進(jìn)程調(diào)用了。多進(jìn)程就是指計(jì)算機(jī)系統(tǒng)可以同時(shí)執(zhí)行多個(gè)進(jìn)程奕剃,從一個(gè)進(jìn)程到另外一個(gè)進(jìn)程的轉(zhuǎn)換是由操作系統(tǒng)內(nèi)核管理的衷旅,一般是同時(shí)運(yùn)行多個(gè)軟件。

[圖片上傳失敗...(image-2296b3-1685598749508)]

線程

有了多進(jìn)程纵朋,為什么還要線程柿顶?原因如下:

  • 進(jìn)程間的信息難以共享數(shù)據(jù),父子進(jìn)程并未共享內(nèi)存操软,需要通過(guò)進(jìn)程間通信(IPC)九串,在進(jìn)程間進(jìn)行信息交換,性能開(kāi)銷(xiāo)較大寺鸥。
  • 創(chuàng)建進(jìn)程(一般是調(diào)用 fork 方法)的性能開(kāi)銷(xiāo)較大猪钮。

在一個(gè)進(jìn)程內(nèi),可以設(shè)置多個(gè)執(zhí)行單元胆建,這個(gè)執(zhí)行單元都運(yùn)行在進(jìn)程的上下文中烤低,共享著同樣的代碼和全局?jǐn)?shù)據(jù),由于是在全局共享的笆载,就不存在像進(jìn)程間信息交換的性能損耗扑馁,所以性能和效率就更高了。這個(gè)運(yùn)行在進(jìn)程中的執(zhí)行單元就是線程凉驻。

[圖片上傳失敗...(image-4188a1-1685598749509)]

協(xié)程

官方的解釋?zhuān)?em>鏈接:goroutines說(shuō)明

Goroutines 是使并發(fā)易于使用的一部分腻要。 這個(gè)想法已經(jīng)存在了一段時(shí)間,就是將獨(dú)立執(zhí)行的函數(shù)(協(xié)程)多路復(fù)用到一組線程上涝登。 當(dāng)協(xié)程阻塞時(shí)雄家,例如通過(guò)調(diào)用阻塞系統(tǒng)調(diào)用,運(yùn)行時(shí)會(huì)自動(dòng)將同一操作系統(tǒng)線程上的其他協(xié)程移動(dòng)到不同的可運(yùn)行線程胀滚,這樣它們就不會(huì)被阻塞趟济。 程序員看不到這些,這就是重點(diǎn)咽笼。 我們稱(chēng)之為 goroutines 的結(jié)果可能非常便宜:除了堆棧的內(nèi)存之外顷编,它們的開(kāi)銷(xiāo)很小,只有幾千字節(jié)剑刑。

為了使堆棧變小媳纬,Go 的運(yùn)行時(shí)使用可調(diào)整大小的有界堆棧。 一個(gè)新創(chuàng)建的 goroutine 被賦予幾千字節(jié),這幾乎總是足夠的钮惠。 如果不是杨伙,運(yùn)行時(shí)會(huì)自動(dòng)增加(和縮小)用于存儲(chǔ)堆棧的內(nèi)存萌腿,從而允許許多 goroutine 存在于適度的內(nèi)存中。 每個(gè)函數(shù)調(diào)用的 CPU 開(kāi)銷(xiāo)平均約為三個(gè)廉價(jià)指令抖苦。 在同一個(gè)地址空間中創(chuàng)建數(shù)十萬(wàn)個(gè) goroutine 是很實(shí)際的毁菱。 如果 goroutines 只是線程,系統(tǒng)資源會(huì)以更少的數(shù)量耗盡锌历。

從官方的解釋中可以看到贮庞,協(xié)程是通過(guò)多路復(fù)用到一組線程上,所以本質(zhì)上究西,協(xié)程就是輕量級(jí)的線程窗慎。但是必須要區(qū)分的一點(diǎn)是,協(xié)程是用用戶態(tài)的卤材,進(jìn)程跟線程都是內(nèi)核態(tài)遮斥,這點(diǎn)非常重要,這也是協(xié)程為什么高效的原因扇丛。

協(xié)程的優(yōu)勢(shì)如下:

  • 節(jié)省 CPU:避免系統(tǒng)內(nèi)核級(jí)的線程頻繁切換术吗,造成的 CPU 資源浪費(fèi)。協(xié)程是用戶態(tài)的線程帆精,用戶可以自行控制協(xié)程的創(chuàng)建于銷(xiāo)毀较屿,極大程度避免了系統(tǒng)級(jí)線程上下文切換造成的資源浪費(fèi)。

  • 節(jié)約內(nèi)存:在 64 位的 Linux 中卓练,一個(gè)線程需要分配 8MB 棧內(nèi)存和 64MB 堆內(nèi)存隘蝎,系統(tǒng)內(nèi)存的制約導(dǎo)致我們無(wú)法開(kāi)啟更多線程實(shí)現(xiàn)高并發(fā)。而在協(xié)程編程模式下襟企,只需要幾千字節(jié)(執(zhí)行Go協(xié)程只需要極少的棧內(nèi)存嘱么,大概4~5KB,默認(rèn)情況下顽悼,線程棧的大小為1MB)可以輕松有十幾萬(wàn)協(xié)程拱撵,這是線程無(wú)法比擬的。

  • 開(kāi)發(fā)效率:使用協(xié)程在開(kāi)發(fā)程序之中表蝙,可以很方便的將一些耗時(shí)的 IO 操作異步化拴测,例如寫(xiě)文件、耗時(shí) IO 請(qǐng)求等府蛇。并且它們并不是被操作系統(tǒng)所調(diào)度執(zhí)行集索,而是程序員手動(dòng)可以進(jìn)行調(diào)度的。

  • 高效率:協(xié)程之間的切換發(fā)生在用戶態(tài),在用戶態(tài)沒(méi)有時(shí)鐘中斷务荆,系統(tǒng)調(diào)用等機(jī)制妆距,因此效率高。


Golang GMP 調(diào)度器

注: 以下相關(guān)知識(shí)摘自劉丹冰(AceLd)的博文:[Golang三關(guān)-典藏版] Golang 調(diào)度器 GMP 原理與調(diào)度全分析

簡(jiǎn)介

  • G 表示:goroutine函匕,即 Go 協(xié)程娱据,每個(gè) go 關(guān)鍵字都會(huì)創(chuàng)建一個(gè)協(xié)程。
  • M 表示:thread 內(nèi)核級(jí)線程盅惜,所有的 G 都要放在 M 上才能運(yùn)行中剩。
  • P 表示:processor 處理器,調(diào)度 GM 上抒寂,其維護(hù)了一個(gè)隊(duì)列结啼,存儲(chǔ)了所有需要它來(lái)調(diào)度的G

Goroutine 調(diào)度器 POS 調(diào)度器是通過(guò) M 結(jié)合起來(lái)的屈芜,每個(gè) M 都代表了 1 個(gè)內(nèi)核線程郊愧,OS 調(diào)度器負(fù)責(zé)把內(nèi)核線程分配到 CPU 的核上執(zhí)行,

線程和協(xié)程的映射關(guān)系

在上面的 Golang 官方關(guān)于協(xié)程的解釋中提到:

將獨(dú)立執(zhí)行的函數(shù)(協(xié)程)多路復(fù)用到一組線程上井佑。 當(dāng)協(xié)程阻塞時(shí)属铁,例如通過(guò)調(diào)用阻塞系統(tǒng)調(diào)用,運(yùn)行時(shí)會(huì)自動(dòng)將同一操作系統(tǒng)線程上的其他協(xié)程移動(dòng)到不同的可運(yùn)行線程躬翁,這樣它們就不會(huì)被阻塞红选。

也就是說(shuō),協(xié)程的執(zhí)行是需要通過(guò)線程來(lái)先實(shí)現(xiàn)的姆另。下圖表示的映射關(guān)系:

[圖片上傳失敗...(image-75293-1685598749509)]

在協(xié)程和線程的映射關(guān)系中喇肋,有以下三種:

  • N:1 關(guān)系
  • 1:1 關(guān)系
  • M:N 關(guān)系

N:1 關(guān)系

N 個(gè)協(xié)程綁定 1 個(gè)線程,優(yōu)點(diǎn)就是協(xié)程在用戶態(tài)線程即完成切換迹辐,不會(huì)陷入到內(nèi)核態(tài)蝶防,這種切換非常的輕量快速。但也有很大的缺點(diǎn)明吩,1 個(gè)進(jìn)程的所有協(xié)程都綁定在 1 個(gè)線程上间学。

缺點(diǎn):

  • 某個(gè)程序用不了硬件的多核加速能力
  • 一旦某協(xié)程阻塞,造成線程阻塞印荔,本進(jìn)程的其他協(xié)程都無(wú)法執(zhí)行了低葫,根本就沒(méi)有并發(fā)的能力了。

[圖片上傳失敗...(image-fcb856-1685598749509)]

1:1 關(guān)系

1 個(gè)協(xié)程綁定 1 個(gè)線程仍律,這種最容易實(shí)現(xiàn)嘿悬。協(xié)程的調(diào)度都由 CPU 完成了,不存在 N:1 缺點(diǎn)水泉。

缺點(diǎn):

  • 協(xié)程的創(chuàng)建善涨、刪除和切換的代價(jià)都由 CPU 完成窒盐,有點(diǎn)略顯昂貴了。

[圖片上傳失敗...(image-4be2a6-1685598749509)]

M:N 關(guān)系

M 個(gè)協(xié)程綁定 1 個(gè)線程钢拧,是 N:11:1 類(lèi)型的結(jié)合蟹漓,克服了以上 2 種模型的缺點(diǎn),但實(shí)現(xiàn)起來(lái)最為復(fù)雜源内。
協(xié)程跟線程是有區(qū)別的葡粒,線程由 CPU 調(diào)度是搶占式的,協(xié)程由用戶態(tài)調(diào)度是協(xié)作式的膜钓,一個(gè)協(xié)程讓出 CPU 后嗽交,才執(zhí)行下一個(gè)協(xié)程。

[圖片上傳失敗...(image-ee7480-1685598749509)]

調(diào)度器實(shí)現(xiàn)原理

注:Go 目前使用的調(diào)度器是 2012 年重新設(shè)計(jì)的呻此。

2012 之前的調(diào)度原理,如下圖所示:

[圖片上傳失敗...(image-c25aea-1685598749509)]

M 想要執(zhí)行腔寡、放回 G 都必須訪問(wèn)全局 G 隊(duì)列焚鲜,并且 M 有多個(gè),即多線程訪問(wèn)同一資源需要加鎖進(jìn)行保證互斥 / 同步放前,所以全局 G 隊(duì)列是有互斥鎖進(jìn)行保護(hù)的忿磅。

缺點(diǎn):

  • 創(chuàng)建、銷(xiāo)毀凭语、調(diào)度 G 都需要每個(gè) M 獲取鎖葱她,這就形成了激烈的鎖競(jìng)爭(zhēng)。
  • M 轉(zhuǎn)移 G 會(huì)造成延遲和額外的系統(tǒng)負(fù)載似扔。比如當(dāng) G 中包含創(chuàng)建新協(xié)程的時(shí)候吨些,M 創(chuàng)建了 G,為了繼續(xù)執(zhí)行 G炒辉,需要把 G 交給 M 執(zhí)行豪墅,也造成了很差的局部性,因?yàn)?GG 是相關(guān)的黔寇,最好放在 M 上執(zhí)行偶器,而不是其他 M
  • 系統(tǒng)調(diào)用 (CPU 在 M 之間的切換) 導(dǎo)致頻繁的線程阻塞和取消阻塞操作增加了系統(tǒng)開(kāi)銷(xiāo)缝裤。

2012 年之后的調(diào)度器實(shí)現(xiàn)原理屏轰,如下圖所示:

[圖片上傳失敗...(image-1e1a61-1685598749509)]

在新調(diào)度器中,除了 M (thread)G (goroutine)憋飞,又引進(jìn)了 P (Processor)霎苗。Processor,它包含了運(yùn)行 goroutine 的資源榛做,如果線程想運(yùn)行 goroutine叨粘,必須先獲取 P猾编,P 中還包含了可運(yùn)行的 G 隊(duì)列。

Go 中升敲,線程是運(yùn)行 goroutine 的實(shí)體答倡,調(diào)度器的功能是把可運(yùn)行的 goroutine 分配到工作線程上。調(diào)度過(guò)程如下:

  1. 全局隊(duì)列(Global Queue):存放等待運(yùn)行的 G驴党。

  2. P 的本地隊(duì)列:同全局隊(duì)列類(lèi)似瘪撇,存放的也是等待運(yùn)行的 G,存的數(shù)量有限港庄,不超過(guò) 256 個(gè)倔既。新建 G 時(shí),G 優(yōu)先加入到 P 的本地隊(duì)列鹏氧,如果隊(duì)列滿了渤涌,則會(huì)把本地隊(duì)列中一半的 G 移動(dòng)到全局隊(duì)列。

  3. P 列表:所有的 P 都在程序啟動(dòng)時(shí)創(chuàng)建把还,并保存在數(shù)組中实蓬,最多有 GOMAXPROCS(可配置) 個(gè)。

  4. M:線程想運(yùn)行任務(wù)就得獲取 P吊履,從 P 的本地隊(duì)列獲取 G安皱,P 隊(duì)列為空時(shí),M 也會(huì)嘗試從全局隊(duì)列拿一批 G 放到 P 的本地隊(duì)列艇炎,或從其他 P 的本地隊(duì)列偷一半放到自己 P 的本地隊(duì)列酌伊。M 運(yùn)行 GG 執(zhí)行之后缀踪,M 會(huì)從 P 獲取下一個(gè) G居砖,不斷重復(fù)下去。

Goroutine 調(diào)度器和 OS 調(diào)度器是通過(guò) M 結(jié)合起來(lái)的驴娃,每個(gè) M 都代表了 1 個(gè)內(nèi)核線程悯蝉,OS 調(diào)度器負(fù)責(zé)把內(nèi)核線程分配到 CPU 的核上執(zhí)行。

調(diào)度器設(shè)計(jì)策略

復(fù)用線程: 避免頻繁的創(chuàng)建托慨、銷(xiāo)毀線程鼻由,而是對(duì)線程的復(fù)用。

  1. work stealing 機(jī)制

當(dāng)本線程無(wú)可運(yùn)行的 G 時(shí)厚棵,嘗試從其他線程綁定的 P 偷取 G蕉世,而不是銷(xiāo)毀線程。

  1. hand off 機(jī)制

當(dāng)本線程因?yàn)?G 進(jìn)行系統(tǒng)調(diào)用阻塞時(shí)婆硬,線程釋放綁定的 P狠轻,把 P 轉(zhuǎn)移給其他空閑的線程執(zhí)行。

  • 利用并行:GOMAXPROCS 設(shè)置 P 的數(shù)量彬犯,最多有 GOMAXPROCS 個(gè)線程分布在多個(gè) CPU 上同時(shí)運(yùn)行向楼。GOMAXPROCS 也限制了并發(fā)的程度查吊,比如 GOMAXPROCS = 核數(shù)/2,則最多利用了一半的 CPU 核進(jìn)行并行湖蜕。

  • 搶占:在 coroutine 中要等待一個(gè)協(xié)程主動(dòng)讓出 CPU 才執(zhí)行下一個(gè)協(xié)程逻卖,在 Go 中,一個(gè) goroutine 最多占用 CPU 10ms昭抒,防止其他 goroutine 被餓死评也,這就是 goroutine 不同于 coroutine 的一個(gè)地方。

  • 全局 G 隊(duì)列:在新的調(diào)度器中依然有全局 G 隊(duì)列灭返,但功能已經(jīng)被弱化了盗迟,當(dāng) M 執(zhí)行 work stealing 從其他 P 偷不到 G 時(shí),它可以從全局 G 隊(duì)列獲取 G熙含。

go func () 調(diào)度流程

[圖片上傳失敗...(image-4eed33-1685598749509)]

流程如下:

  1. 通過(guò) go func () 來(lái)創(chuàng)建一個(gè) goroutine
  2. 有兩個(gè)存儲(chǔ) G 的隊(duì)列罚缕,一個(gè)是局部調(diào)度器 P 的本地隊(duì)列、一個(gè)是全局 G 隊(duì)列怎静。新創(chuàng)建的 G 會(huì)先保存在 P 的本地隊(duì)列中邮弹,如果 P 的本地隊(duì)列已經(jīng)滿了就會(huì)保存在全局的隊(duì)列中;
  3. G 只能運(yùn)行在 M 中消约,一個(gè) M 必須持有一個(gè) P肠鲫,MP1:1 的關(guān)系员帮。M 會(huì)從 P 的本地隊(duì)列彈出一個(gè)可執(zhí)行狀態(tài)的 G 來(lái)執(zhí)行或粮,如果 P 的本地隊(duì)列為空,就會(huì)向其他的 MP 組合偷取一個(gè)可執(zhí)行的 G 來(lái)執(zhí)行捞高;
  4. 一個(gè) M 調(diào)度 G 執(zhí)行的過(guò)程是一個(gè)循環(huán)機(jī)制氯材;
  5. 當(dāng) M 執(zhí)行某一個(gè) G 時(shí)候如果發(fā)生了 syscall 或則其余阻塞操作,M 會(huì)阻塞硝岗,如果當(dāng)前有一些 G 在執(zhí)行氢哮,runtime 會(huì)把這個(gè)線程 MP 中摘除 (detach),然后再創(chuàng)建一個(gè)新的操作系統(tǒng)的線程 (如果有空閑的線程可用就復(fù)用空閑線程) 來(lái)服務(wù)于這個(gè) P型檀;
  6. 當(dāng) M 系統(tǒng)調(diào)用結(jié)束時(shí)候冗尤,這個(gè) G 會(huì)嘗試獲取一個(gè)空閑的 P 執(zhí)行,并放入到這個(gè) P 的本地隊(duì)列胀溺。如果獲取不到 P裂七,那么這個(gè)線程 M 變成休眠狀態(tài), 加入到空閑線程中仓坞,然后這個(gè) G 會(huì)被放入全局隊(duì)列中背零。

調(diào)度器的生命周期

[圖片上傳失敗...(image-ad8cd5-1685598749509)]

特殊的 M0G0

M0

M0 是啟動(dòng)程序后的編號(hào)為 0 的主線程,這個(gè) M 對(duì)應(yīng)的實(shí)例會(huì)在全局變量 runtime.m0 中无埃,不需要在 heap 上分配徙瓶,M0 負(fù)責(zé)執(zhí)行初始化操作和啟動(dòng)第一個(gè) G毛雇, 在之后 M0 就和其他的 M 一樣了。

G0

G0 是每次啟動(dòng)一個(gè) M 都會(huì)第一個(gè)創(chuàng)建的 goroutine侦镇,G0 僅用于負(fù)責(zé)調(diào)度的 G灵疮,G0 不指向任何可執(zhí)行的函數(shù),每個(gè) M 都會(huì)有一個(gè)自己的 G0虽缕。在調(diào)度或系統(tǒng)調(diào)用時(shí)會(huì)使用 G0 的検寂海空間,全局變量的 G0M0G0氮趋。

我們來(lái)跟蹤一段代碼:

package main

import "fmt"

func main() {
    fmt.Println("Hello world")
}

接下來(lái)我們來(lái)針對(duì)上面的代碼對(duì)調(diào)度器里面的結(jié)構(gòu)做一個(gè)分析伍派,也會(huì)經(jīng)歷如上圖所示的過(guò)程:

  1. runtime 創(chuàng)建最初的線程 m0goroutine g0,并把 2 者關(guān)聯(lián)剩胁。
  2. 調(diào)度器初始化:初始化 m0诉植、棧、垃圾回收昵观,以及創(chuàng)建和初始化由 GOMAXPROCS 個(gè) P 構(gòu)成的 P 列表晾腔。
  3. 示例代碼中的 main 函數(shù)是 main.mainruntime 中也有 1 個(gè) main 函數(shù) ——runtime.main啊犬,代碼經(jīng)過(guò)編譯后灼擂,runtime.main 會(huì)調(diào)用 main.main,程序啟動(dòng)時(shí)會(huì)為 runtime.main 創(chuàng)建 goroutine觉至,稱(chēng)它為 main goroutine 吧剔应,然后把 main goroutine 加入到 P 的本地隊(duì)列。
  4. 啟動(dòng) m0语御,m0 已經(jīng)綁定了 P峻贮,會(huì)從 P 的本地隊(duì)列獲取 G,獲取到 main goroutine应闯。
  5. G 擁有棧纤控,M 根據(jù) G 中的棧信息和調(diào)度信息設(shè)置運(yùn)行環(huán)境。
  6. M 運(yùn)行 G碉纺。
  7. G 退出船万,再次回到 M 獲取可運(yùn)行的 G,這樣重復(fù)下去骨田,直到 main.main 退出耿导,runtime.main 執(zhí)行 DeferPanic 處理,或調(diào)用 runtime.exit 退出程序盛撑。

調(diào)度器的生命周期幾乎占滿了一個(gè) Go 程序的一生碎节,runtime.maingoroutine 執(zhí)行之前都是為調(diào)度器做準(zhǔn)備工作,runtime.maingoroutine 運(yùn)行抵卫,才是調(diào)度器的真正開(kāi)始狮荔,直到 runtime.main 結(jié)束而結(jié)束胎撇。


轉(zhuǎn)載請(qǐng)注明來(lái)源:https://janrs.com/mffp

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市殖氏,隨后出現(xiàn)的幾起案子晚树,更是在濱河造成了極大的恐慌,老刑警劉巖雅采,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爵憎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡婚瓜,警方通過(guò)查閱死者的電腦和手機(jī)宝鼓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巴刻,“玉大人愚铡,你說(shuō)我怎么就攤上這事『悖” “怎么了沥寥?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)柠座。 經(jīng)常有香客問(wèn)我邑雅,道長(zhǎng),這世上最難降的妖魔是什么妈经? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任淮野,我火速辦了婚禮,結(jié)果婚禮上狂塘,老公的妹妹穿的比我還像新娘录煤。我一直安慰自己鳄厌,他們只是感情好荞胡,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著了嚎,像睡著了一般泪漂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上歪泳,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天萝勤,我揣著相機(jī)與錄音,去河邊找鬼呐伞。 笑死敌卓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的伶氢。 我是一名探鬼主播趟径,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼瘪吏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜗巧?” 一聲冷哼從身側(cè)響起掌眠,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎幕屹,沒(méi)想到半個(gè)月后蓝丙,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡望拖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年渺尘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片说敏。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沧烈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出像云,到底是詐尸還是另有隱情锌雀,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布迅诬,位于F島的核電站腋逆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侈贷。R本人自食惡果不足惜惩歉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俏蛮。 院中可真熱鬧撑蚌,春花似錦、人聲如沸搏屑。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辣恋。三九已至亮垫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間伟骨,已是汗流浹背饮潦。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留携狭,地道東北人继蜡。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親稀并。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲫剿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容