作為java開發(fā)工作人員必備的高并發(fā)編程知識體系(一)

高并發(fā)編程知識體系

1.問題

1所坯、什么是線程的交互方式?

2挂捅、如何區(qū)分線程的同步/異步芹助,阻塞/非阻塞?

3闲先、什么是線程安全状土,如何做到線程安全?

4伺糠、如何區(qū)分并發(fā)模型蒙谓?

5、何謂響應(yīng)式編程退盯?

6彼乌、操作系統(tǒng)如何調(diào)度多線程?

2.關(guān)鍵詞

同步渊迁,異步慰照,阻塞,非阻塞琉朽,并行毒租,并發(fā),臨界區(qū),競爭條件墅垮,指令重排惕医,鎖,amdahl,gustafson

3.全文概要

由于單機(jī)的性能上限原因我們才不得不發(fā)展分布式技術(shù)算色。那么話說回來抬伺,如果單機(jī)的性能沒能最大限度的榨取出來,就盲目的就建設(shè)分布式系統(tǒng)灾梦,那就有點(diǎn)本末倒置了峡钓。如果單機(jī)性能滿足的話,就不要折騰復(fù)雜的分布式架構(gòu)若河。如果說分布式架構(gòu)是宏觀上的性能擴(kuò)展能岩,那么高并發(fā)則是微觀上的性能調(diào)優(yōu)。本文將從線程的基礎(chǔ)理論談起萧福,逐步探究線程的內(nèi)存模型拉鹃,線程的交互,線程工具和并發(fā)模型的發(fā)展鲫忍。掃除關(guān)于并發(fā)編程的諸多模糊概念膏燕,從新構(gòu)建并發(fā)編程的層次結(jié)構(gòu)。

4.基礎(chǔ)理論

4.1基本概念

開始學(xué)習(xí)并發(fā)編程前饲窿,我們需要熟悉一些理論概念煌寇。既然我們要研究的是并發(fā)編程,那首先應(yīng)該對并發(fā)這個概念有所理解才是逾雄,而說到并發(fā)我們肯定要要討論一些并行阀溶。

并發(fā):一個處理器同時處理多個任務(wù)

并行:多個處理器或者是多核的處理器同時處理多個不同的任務(wù)

然后我們需要再了解一下同步和異步的區(qū)別:

同步:執(zhí)行某個操作開始后就一直等著按部就班的直到操作結(jié)束

異步:執(zhí)行某個操作后立即離開,后面有響應(yīng)的話再來通知執(zhí)行者

接著我們再了解一個重要的概念:

臨界區(qū):公共資源或者共享數(shù)據(jù)

由于共享數(shù)據(jù)的出現(xiàn)鸦泳,必然會導(dǎo)致競爭银锻,所以我們需要再了解一下:

阻塞:某個操作需要的共享資源被占用了,只能等待做鹰,稱為阻塞

非阻塞:某個操作需要的共享資源被占用了击纬,不等待立即返回,并攜帶錯誤信息回去钾麸,期待重試

如果兩個操作都在等待某個共享資源而且都互不退讓就會造成死鎖:

死鎖:參考著名的哲學(xué)家吃飯問題

饑餓:饑餓的哲學(xué)家等不齊筷子吃飯

活鎖:相互謙讓而導(dǎo)致阻塞無法進(jìn)入下一步操作更振,跟死鎖相反,死鎖是相互競爭而導(dǎo)致的阻塞

4.2并發(fā)級別

理想情況下我們希望所有線程都一起并行飛起來饭尝。但是CPU數(shù)量有限肯腕,線程源源不斷,總得有個先來后到钥平,不同場景需要的并發(fā)需求也不一樣实撒,比如秒殺系統(tǒng)我們需要很高的并發(fā)程度,但是對于一些下載服務(wù),我們需要的是更快的響應(yīng)知态,并發(fā)反而是其次的捷兰。所以我們也定義了并發(fā)的級別,來應(yīng)對不同的需求場景负敏。

阻塞:阻塞是指一個線程進(jìn)入臨界區(qū)后贡茅,其它線程就必須在臨界區(qū)外等待,待進(jìn)去的線程執(zhí)行完任務(wù)離開臨界區(qū)后其做,其它線程才能再進(jìn)去友扰。

無饑餓:線程排隊(duì)先來后到,不管優(yōu)先級大小庶柿,先來先執(zhí)行,就不會產(chǎn)生饑餓等待資源秽浇,也即公平鎖浮庐;相反非公平鎖則是根據(jù)優(yōu)先級來執(zhí)行,有可能排在前面的低優(yōu)先級線程被后面的高優(yōu)先級線程插隊(duì)柬焕,就形成饑餓

無障礙:共享資源不加鎖审残,每個線程都可以自有讀寫,單監(jiān)測到被其他線程修改過則回滾操作斑举,重試直到單獨(dú)操作成功搅轿;風(fēng)險就是如果多個線程發(fā)現(xiàn)彼此修改了,所有線程都需要回滾富玷,就會導(dǎo)致死循環(huán)的回滾中璧坟,造成死鎖

無鎖:無鎖是無障礙的加強(qiáng)版,無鎖級別保證至少有一個線程在有限操作步驟內(nèi)成功退出赎懦,不管是否修改成功雀鹃,這樣保證了多個線程回滾不至于導(dǎo)致死循環(huán)

無等待:無等待是無鎖的升級版,并發(fā)編程的最高境界励两,無鎖只保證有線程能成功退出黎茎,但存在低級別的線程一直處于饑餓狀態(tài),無等待則要求所有線程必須在有限步驟內(nèi)完成退出当悔,讓低級別的線程有機(jī)會執(zhí)行傅瞻,從而保證所有線程都能運(yùn)行,提高并發(fā)度盲憎。

4.3量化模型

首先嗅骄,多線程不意味著并發(fā),但并發(fā)肯定是多線程或者多進(jìn)程焙畔。我們知道多線程存在的優(yōu)勢是能夠更好的利用資源掸读,有更快的請求響應(yīng)。但是我們也深知一旦進(jìn)入多線程,附帶而來的是更高的編碼復(fù)雜度儿惫,線程設(shè)計(jì)不當(dāng)反而會帶來更高的切換成本和資源開銷澡罚。但是總體上我們肯定知道利大于弊,這不是廢話嗎肾请,不然誰還愿意去搞多線程并發(fā)程序留搔,但是如何衡量多線程帶來的效率提升呢,我們需要借助兩個定律來衡量铛铁。

Amdahl

S=1/(1-a+a/n)

其中隔显,a為并行計(jì)算部分所占比例,n為并行處理結(jié)點(diǎn)個數(shù)饵逐。這樣括眠,當(dāng)1-a=0時,(即沒有串行倍权,只有并行)最大加速比s=n掷豺;當(dāng)a=0時(即只有串行,沒有并行)薄声,最小加速比s=1当船;當(dāng)n→∞時,極限加速比s→ 1/(1-a)默辨,這也就是加速比的上限德频。

Gustafson

系統(tǒng)優(yōu)化某部件所獲得的系統(tǒng)性能的改善程度,取決于該部件被使用的頻率缩幸,或所占總執(zhí)行時間的比例壹置。

兩面列舉了這兩個定律來衡量系統(tǒng)改善后提升效率的量化指標(biāo),具體的應(yīng)用我們在下文的線程調(diào)優(yōu)會再詳細(xì)介紹桌粉。

5.內(nèi)存模型

宏觀上分布式系統(tǒng)需要解決的首要問題是數(shù)據(jù)一致性蒸绩,同樣,微觀上并發(fā)編程要解決的首要問題也是數(shù)據(jù)一致性铃肯。貌似我們搞了這么多年的斗爭都是在公關(guān)一致性這個世界性難題患亿。既然并發(fā)編程要從微觀開始,那么我們肯定要對CPU和內(nèi)存的工作機(jī)理有所了解押逼,尤其是數(shù)據(jù)在CPU和內(nèi)存直接的傳輸機(jī)制步藕。

5.1整體原則

探究內(nèi)存模型之前我們要拋出三個概念:

原子性

在32位的系統(tǒng)中,對于4個字節(jié)32位的Integer的操作對應(yīng)的JVM指令集映射到匯編指令為一個原子操作挑格,所以對Integer類型的數(shù)據(jù)操作是原子性咙冗,但是Long類型為8個字節(jié)64位,32位系統(tǒng)要分為兩條指令來操作漂彤,所以不是原子操作雾消。

對于32位操作系統(tǒng)來說灾搏,單次次操作能處理的最長長度為32bit,而long類型8字節(jié)64bit立润,所以對long的讀寫都要兩條指令才能完成(即每次讀寫64bit中的32bit)

可見性

線程修改變量對其他線程即時可見

有序性

串行指令順序唯一狂窑,并行線程直接指令可能出現(xiàn)不一致,也即是指令被重排了

而指令重排也是有一定原則(摘自《深入理解Java虛擬機(jī)第12章》):

程序次序規(guī)則:一個線程內(nèi)桑腮,按照代碼順序泉哈,書寫在前面的操作先行發(fā)生于書寫在后面的操作;

鎖定規(guī)則:一個unLock操作先行發(fā)生于后面對同一個鎖額lock操作破讨;

volatile變量規(guī)則:對一個變量的寫操作先行發(fā)生于后面對這個變量的讀操作丛晦;

傳遞規(guī)則:如果操作A先行發(fā)生于操作B,而操作B又先行發(fā)生于操作C提陶,則可以得出操作A先行發(fā)生于操作C烫沙;

線程啟動規(guī)則:Thread對象的start()方法先行發(fā)生于此線程的每個一個動作;

線程中斷規(guī)則:對線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程的代碼檢測到中斷事件的發(fā)生隙笆;

線程終結(jié)規(guī)則:線程中所有的操作都先行發(fā)生于線程的終止檢測斧吐,我們可以通過Thread.join()方法結(jié)束、Thread.isAlive()的返回值手段檢測到線程已經(jīng)終止執(zhí)行仲器;

對象終結(jié)規(guī)則:一個對象的初始化完成先行發(fā)生于他的finalize()方法的開始;

5.2邏輯內(nèi)存

我們談的邏輯內(nèi)存也即是JVM的內(nèi)存格局仰冠。JVM將操作系統(tǒng)提供的物理內(nèi)存和CPU緩存在邏輯分為堆乏冀,棧,方法區(qū)洋只,和程序計(jì)數(shù)器辆沦。在《從宏觀微觀角度淺析JVM虛擬機(jī)》 一文我們詳細(xì)介紹了JVM的內(nèi)存模型分布,并發(fā)編程我們主要關(guān)注的是堆棧的分配识虚,因?yàn)榫€程都是寄生在棧里面的內(nèi)存段肢扯,把棧里面的方法邏輯讀取到CPU進(jìn)行運(yùn)算。

5.3物理內(nèi)存

而實(shí)際的物理內(nèi)存包含了主存和CPU的各級緩存還有寄存器担锤,而為了計(jì)算效率蔚晨,CPU往往回就近從緩存里面讀取數(shù)據(jù)。在并發(fā)的情況下就會造成多個線程之間對共享數(shù)據(jù)的錯誤使用肛循。

5.4內(nèi)存映射

由于可能發(fā)生對象的變量同時出現(xiàn)在主存和CPU緩存中铭腕,就可能導(dǎo)致了如下問題:

線程修改的變量對外可見

讀寫共享變量時出現(xiàn)競爭資源

由于線程內(nèi)的變量對棧外是不可見的,但是成員變量等共享資源是競爭條件多糠,所有線程可見累舷,就會出現(xiàn)如下當(dāng)一個線程從主存拿了一個變量1修改后變成2存放在CPU緩存,還沒來得及同步回主存時夹孔,另外一個線程又直接從主存讀取變量為1被盈,這樣就出現(xiàn)了臟讀析孽。

現(xiàn)在我們弄清楚了線程同步過程數(shù)據(jù)不一致的原因,接下來要解決的目標(biāo)就是如何避免這種情況的發(fā)生只怎,經(jīng)過大量的探索和實(shí)踐袜瞬,我們從概念上不斷的革新比如并發(fā)模型的流水線化和無狀態(tài)函數(shù)式化,而且也提供了大量的實(shí)用工具尝盼。接下來我們從無到有吞滞,先了解最簡單的單個線程的一些特點(diǎn),弄清楚一個線程有多少能耐后盾沫,才能深刻認(rèn)識多個線程一起打交道會出現(xiàn)什么幺蛾子裁赠。

6.線程單元

6.1狀態(tài)

我們知道應(yīng)用啟動體現(xiàn)的就是靜態(tài)指令加載進(jìn)內(nèi)存,進(jìn)而進(jìn)入CPU運(yùn)算赴精,操作系統(tǒng)在內(nèi)存開辟了一段棧內(nèi)存用來存放指令和變量值佩捞,從而形成了進(jìn)程。而其實(shí)我們的JVM也就是一個進(jìn)程而且蕾哟,而線程是進(jìn)程的最小單位一忱,也就是說進(jìn)程是由很多個線程組成的。而由于進(jìn)程的上下文關(guān)聯(lián)的變量谭确,引用帘营,計(jì)數(shù)器等現(xiàn)場數(shù)據(jù)占用了打段的內(nèi)存空間,所以頻繁切換進(jìn)程需要整理一大段內(nèi)存空間來保存未執(zhí)行完的進(jìn)程現(xiàn)場逐哈,等下次輪到CPU時間片再恢復(fù)現(xiàn)場進(jìn)行運(yùn)算芬迄。這樣既耗費(fèi)時間又浪費(fèi)空間,所以我們才要研究多線程昂秃。畢竟由于線程干的活畢竟少禀梳,工作現(xiàn)場數(shù)據(jù)畢竟少,所以切換起來比較快而且暫用少量空間肠骆。而線程切換直接也需要遵守一定的法則算途,不然到時候把工作現(xiàn)場破壞了就無法恢復(fù)工作了。

線程狀態(tài)

我們先來研究線程的生命周期蚀腿,看看Thread類里面對線程狀態(tài)的定義就知道

public enum State { /**

* Thread state for a thread which has not yet started.

*/

NEW, /**

* Thread state for a runnable thread. A thread in the runnable

* state is executing in the Java virtual machine but it may

* be waiting for other resources from the operating system

* such as processor.

*/

RUNNABLE, /**

* Thread state for a thread blocked waiting for a monitor lock.

* A thread in the blocked state is waiting for a monitor lock

* to enter a synchronized block/method or

* reenter a synchronized block/method after calling

* {@link Object#wait() Object.wait}.

*/

BLOCKED, /**

* Thread state for a waiting thread.

* A thread is in the waiting state due to calling one of the

* following methods:

*

    *

  • {@link Object#wait() Object.wait} with no timeout
  • *

  • {@link #join() Thread.join} with no timeout
  • *

  • {@link LockSupport#park() LockSupport.park}
  • *

    *

    *

    A thread in the waiting state is waiting for another thread to

    * perform a particular action.

    *

    * For example, a thread that has called Object.wait()

    * on an object is waiting for another thread to call

    * Object.notify() or Object.notifyAll() on

    * that object. A thread that has called Thread.join()

    * is waiting for a specified thread to terminate.

    */

    WAITING, /**

    * Thread state for a waiting thread with a specified waiting time.

    * A thread is in the timed waiting state due to calling one of

    * the following methods with a specified positive waiting time:

    *

      *

    • {@link #sleep Thread.sleep}
    • *

    • {@link Object#wait(long) Object.wait} with timeout
    • *

    • {@link #join(long) Thread.join} with timeout
    • *

    • {@link LockSupport#parkNanos LockSupport.parkNanos}
    • *

    • {@link LockSupport#parkUntil LockSupport.parkUntil}
    • *

      */

      TIMED_WAITING, /**

      * Thread state for a terminated thread.

      * The thread has completed execution.

      */

      TERMINATED;

      }

      生命周期

      線程的狀態(tài):NEW嘴瓤,RUNNABLE,BLOCKED莉钙,WAITING纱注,TIMED_WAITING,TERMINATED胆胰。注釋也解釋得很清楚各個狀態(tài)的作用狞贱,而各個狀態(tài)的轉(zhuǎn)換也有一定的規(guī)則需要遵循的。

      6.2動作

      介紹完線程的狀態(tài)和生命周期蜀涨,接下來我了解的線程具備哪些常用的操作瞎嬉。首先線程也是一個普通的對象Thread蝎毡,所有的線程都是Thread或者其子類的對象。那么這個內(nèi)存對象被創(chuàng)建出來后就會放在JVM的堆內(nèi)存空間氧枣,當(dāng)我們執(zhí)行start()方法的時候沐兵,對象的方法體在棧空間分配好對應(yīng)的棧幀來往執(zhí)行引擎輸送指令(也即是方法體翻譯成JVM的指令集)便监。

      線程操作

      新建線程:new Thread()扎谎,新建一個線程對象,內(nèi)存為線程在棧上分配好內(nèi)存空間

      啟動線程:start()烧董,告訴系統(tǒng)系統(tǒng)準(zhǔn)備就緒毁靶,只要資源允許隨時可以執(zhí)行我棧里面的指令了

      執(zhí)行線程:run(),分配了CPU等計(jì)算資源逊移,正在執(zhí)行棧里面的指令集

      停止線程(過時):stop()预吆,把CPU和內(nèi)存資源回收,線程消亡胳泉,由于太過粗暴拐叉,已經(jīng)被標(biāo)記為過時

      線程中斷:

      interrupt(),中斷是對線程打上了中斷標(biāo)簽扇商,可供run()里面的方法體接收中斷信號凤瘦,至于線程要不要中斷,全靠業(yè)務(wù)邏輯設(shè)計(jì)案铺,而不是簡單粗暴的把線程直接停掉

      isInterrupt()廷粒,主要是run()方法體來判斷當(dāng)前線程是否被置為中斷

      interrupted(),靜態(tài)方法红且,也是用戶判斷線程是否被置為中斷狀態(tài),同時判斷完將線程中斷狀態(tài)復(fù)位

      線程休眠:sleep()涤姊,靜態(tài)方法暇番,線程休眠指定時間段,此間讓出CPU資源給其他線程思喊,但是線程依然持有對象鎖壁酬,其他線程無法進(jìn)入同步塊,休眠完成后也未必立刻執(zhí)行恨课,需要等到資源允許才能執(zhí)行

      線程等待(對象方法):wait()舆乔,是Object的方法,也即是對象的內(nèi)置方法剂公,在同步塊中線程執(zhí)行到該方法時希俩,也即讓出了該對象的鎖,所以無法繼續(xù)執(zhí)行

      線程通知(對象方法):notify(),notifyAll()纲辽,此時該對象持有一個或者多個線程的wait颜武,調(diào)用notify()隨機(jī)的讓一個線程恢復(fù)對象的鎖璃搜,調(diào)用notifyAll()則讓所有線程恢復(fù)對象鎖

      線程掛起(過時):suspend(),線程掛起并沒有釋放資源鳞上,而是只能等到resume()才能繼續(xù)執(zhí)行

      線程恢復(fù)(過時):resume()这吻,由于指令重排可能導(dǎo)致resume()先于suspend()執(zhí)行,導(dǎo)致線程永遠(yuǎn)掛起篙议,所以該方法被標(biāo)為過時

      線程加入:join()唾糯,在一個線程調(diào)用另外一個線程的join()方法表明當(dāng)前線程阻塞知道被調(diào)用線程執(zhí)行結(jié)束再進(jìn)行,也即是被調(diào)用線程織入進(jìn)來

      線程讓步:yield()鬼贱,暫停當(dāng)前線程進(jìn)而執(zhí)行別的線程移怯,當(dāng)前線程等待下一輪資源允許再進(jìn)行,防止該線程一直霸占資源吩愧,而其他線程餓死

      線程等待:park()芋酌,基于線程對象的操作,較對象鎖更為精準(zhǔn)

      線程恢復(fù):unpark(Thread thread)雁佳,對應(yīng)park()解鎖脐帝,為不可重入鎖

      線程分組

      為了管理線程,于是有了線程組的概念糖权,業(yè)務(wù)上把類似的線程放在一個ThreadGroup里面統(tǒng)一管理堵腹。線程組表示一組線程,此外星澳,線程組還可以包括其他線程組疚顷。線程組形成一個樹,其中除了初始線程組以外的每個線程組都有一個父線程禁偎。線程被允許訪問它自己的線程組信息腿堤,但不能訪問線程組的父線程組或任何其他線程組的信息。

      守護(hù)線程

      通常情況下如暖,線程運(yùn)行到最后一條指令后則完成生命周期笆檀,結(jié)束線程,然后系統(tǒng)回收資源盒至⌒锶鳎或者單遇到異常或者return提前返回枷遂,但是如果我們想讓線程常駐內(nèi)存的話数冬,比如一些監(jiān)控類線程怎燥,需要24小時值班的县爬,于是我們又創(chuàng)造了守護(hù)線程的概念委乌。

      setDaemon()傳入true則會把線程一直保持在內(nèi)存里面,除非JVM宕機(jī)否則不會退出痪伦。

      線程優(yōu)先級

      線程優(yōu)先級其實(shí)只是對線程打的一個標(biāo)志耍鬓,但并不意味這高優(yōu)先級的一定比低優(yōu)先級的先執(zhí)行阔籽,具體還要看操作系統(tǒng)的資源調(diào)度情況。通常線程優(yōu)先級為5牲蜀,邊界為[1,10]笆制。

      /**

      * The minimum priority that a thread can have.

      */

      public final static int MIN_PRIORITY = 1;/**

      * The default priority that is assigned to a thread.

      */

      public final static int NORM_PRIORITY = 5; /**

      * The maximum priority that a thread can have.

      */

      public final static int MAX_PRIORITY = 10;

      本節(jié)介紹了線程單元的轉(zhuǎn)態(tài)切換和常用的一些操作方法。如果只是單線程的話涣达,其他都沒必要研究這些在辆,重頭戲在于多線程直接的競爭配合操作,下一節(jié)則重點(diǎn)介紹多個線程的交互需要關(guān)注哪些問題度苔。

      本文主要將的數(shù)基于JAVA的傳統(tǒng)多線程并發(fā)模型匆篓,下面例牌給出知識體系圖。

      視頻資料領(lǐng)取??? 微信:Nancy007001

      原創(chuàng): 編程原理林振華

      ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
      • 序言:七十年代末寇窑,一起剝皮案震驚了整個濱河市鸦概,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌甩骏,老刑警劉巖窗市,帶你破解...
        沈念sama閱讀 216,591評論 6 501
      • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異饮笛,居然都是意外死亡咨察,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
        沈念sama閱讀 92,448評論 3 392
      • 文/潘曉璐 我一進(jìn)店門福青,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摄狱,“玉大人,你說我怎么就攤上這事无午∶揭郏” “怎么了?”我有些...
        開封第一講書人閱讀 162,823評論 0 353
      • 文/不壞的土叔 我叫張陵宪迟,是天一觀的道長酣衷。 經(jīng)常有香客問我,道長踩验,這世上最難降的妖魔是什么? 我笑而不...
        開封第一講書人閱讀 58,204評論 1 292
      • 正文 為了忘掉前任商玫,我火速辦了婚禮箕憾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拳昌。我一直安慰自己袭异,他們只是感情好,可當(dāng)我...
        茶點(diǎn)故事閱讀 67,228評論 6 388
      • 文/花漫 我一把揭開白布炬藤。 她就那樣靜靜地躺著御铃,像睡著了一般碴里。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上上真,一...
        開封第一講書人閱讀 51,190評論 1 299
      • 那天咬腋,我揣著相機(jī)與錄音,去河邊找鬼睡互。 笑死根竿,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的就珠。 我是一名探鬼主播寇壳,決...
        沈念sama閱讀 40,078評論 3 418
      • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妻怎!你這毒婦竟也來了壳炎?” 一聲冷哼從身側(cè)響起,我...
        開封第一講書人閱讀 38,923評論 0 274
      • 序言:老撾萬榮一對情侶失蹤逼侦,失蹤者是張志新(化名)和其女友劉穎匿辩,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體偿洁,經(jīng)...
        沈念sama閱讀 45,334評論 1 310
      • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撒汉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
        茶點(diǎn)故事閱讀 37,550評論 2 333
      • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了涕滋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睬辐。...
        茶點(diǎn)故事閱讀 39,727評論 1 348
      • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖宾肺,靈堂內(nèi)的尸體忽然破棺而出溯饵,到底是詐尸還是另有隱情,我是刑警寧澤锨用,帶...
        沈念sama閱讀 35,428評論 5 343
      • 正文 年R本政府宣布丰刊,位于F島的核電站,受9級特大地震影響增拥,放射性物質(zhì)發(fā)生泄漏啄巧。R本人自食惡果不足惜,卻給世界環(huán)境...
        茶點(diǎn)故事閱讀 41,022評論 3 326
      • 文/蒙蒙 一掌栅、第九天 我趴在偏房一處隱蔽的房頂上張望秩仆。 院中可真熱鬧,春花似錦猾封、人聲如沸澄耍。這莊子的主人今日做“春日...
        開封第一講書人閱讀 31,672評論 0 22
      • 文/蒼蘭香墨 我抬頭看了看天上的太陽齐莲。三九已至痢站,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間选酗,已是汗流浹背阵难。 一陣腳步聲響...
        開封第一講書人閱讀 32,826評論 1 269
      • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留星掰,地道東北人多望。 一個月前我還...
        沈念sama閱讀 47,734評論 2 368
      • 正文 我出身青樓,卻偏偏與公主長得像氢烘,于是被迫代替她去往敵國和親怀偷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
        茶點(diǎn)故事閱讀 44,619評論 2 354

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