Java的volatile關(guān)鍵字

在Java相關(guān)的崗位面試中夫晌,很多面試官都喜歡考察面試者對(duì)Java并發(fā)的了解程度,而以volatile關(guān)鍵字作為一個(gè)小的切入點(diǎn)昧诱,往往可以一問(wèn)到底晓淀,把Java內(nèi)存模型(JMM),Java并發(fā)編程的一些特性都牽扯出來(lái)鳄哭,深入地話(huà)還可以考察JVM底層實(shí)現(xiàn)以及操作系統(tǒng)的相關(guān)知識(shí)要糊。

下面我們以一次假想的面試過(guò)程,來(lái)深入了解下volitile關(guān)鍵字吧妆丘!

面試官: Java并發(fā)這塊了解的怎么樣锄俄?說(shuō)說(shuō)你對(duì)volatile關(guān)鍵字的理解

就我理解的而言,被volatile修飾的共享變量勺拣,就具有了以下兩點(diǎn)特性:

1 . 保證了不同線程對(duì)該變量操作的內(nèi)存可見(jiàn)性;

2 . 禁止指令重排序

面試官: 能不能詳細(xì)說(shuō)下什么是內(nèi)存可見(jiàn)性奶赠,什么又是重排序呢?

這個(gè)聊起來(lái)可就多了药有,我還是從Java內(nèi)存模型說(shuō)起吧毅戈。

Java虛擬機(jī)規(guī)范試圖定義一種Java內(nèi)存模型(JMM),來(lái)屏蔽掉各種硬件和操作系統(tǒng)的內(nèi)存訪問(wèn)差異,讓Java程序在各種平臺(tái)上都能達(dá)到一致的內(nèi)存訪問(wèn)效果愤惰。簡(jiǎn)單來(lái)說(shuō)苇经,由于CPU執(zhí)行指令的速度是很快的,但是內(nèi)存訪問(wèn)的速度就慢了很多宦言,相差的不是一個(gè)數(shù)量級(jí)扇单,所以搞處理器的那群大佬們又在CPU里加了好幾層高速緩存。

在Java內(nèi)存模型里奠旺,對(duì)上述的優(yōu)化又進(jìn)行了一波抽象蜘澜。JMM規(guī)定所有變量都是存在主存中的,類(lèi)似于上面提到的普通內(nèi)存响疚,每個(gè)線程又包含自己的工作內(nèi)存鄙信,方便理解就可以看成CPU上的寄存器或者高速緩存。所以線程的操作都是以工作內(nèi)存為主忿晕,它們只能訪問(wèn)自己的工作內(nèi)存装诡,且工作前后都要把值在同步回主內(nèi)存。

這么說(shuō)得我自己都有些不清楚了,拿張紙畫(huà)一下:

image

在線程執(zhí)行時(shí)慎王,首先會(huì)從主存中read變量值蚓土,再load到工作內(nèi)存中的副本中宏侍,然后再傳給處理器執(zhí)行赖淤,執(zhí)行完畢后再給工作內(nèi)存中的副本賦值,隨后工作內(nèi)存再把值傳回給主存谅河,主存中的值才更新咱旱。

使用工作內(nèi)存和主存,雖然加快的速度绷耍,但是也帶來(lái)了一些問(wèn)題吐限。比如看下面一個(gè)例子:

i = i + 1;

假設(shè)i初值為0,當(dāng)只有一個(gè)線程執(zhí)行它時(shí)褂始,結(jié)果肯定得到1诸典,當(dāng)兩個(gè)線程執(zhí)行時(shí),會(huì)得到結(jié)果2嗎崎苗?這倒不一定了狐粱。可能存在這種情況:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

線程1: load i from 主存 // i = 0

    i + 1  // i = 1

線程2: load i from主存 // 因?yàn)榫€程1還沒(méi)將i的值寫(xiě)回主存胆数,所以i還是0

    i +  1 //i = 1

線程1: save i to 主存

線程2: save i to 主存

</pre>

如果兩個(gè)線程按照上面的執(zhí)行流程肌蜻,那么i最后的值居然是1了。如果最后的寫(xiě)回生效的慢必尼,你再讀取i的值蒋搜,都可能是0,這就是緩存不一致問(wèn)題判莉。

下面就要提到你剛才問(wèn)到的問(wèn)題了豆挽,JMM主要就是圍繞著如何在并發(fā)過(guò)程中如何處理原子性、可見(jiàn)性和有序性這3個(gè)特征來(lái)建立的券盅,通過(guò)解決這三個(gè)問(wèn)題帮哈,可以解除緩存不一致的問(wèn)題。而volatile跟可見(jiàn)性和有序性都有關(guān)渗饮。

面試官:那你具體說(shuō)說(shuō)這三個(gè)特性呢但汞?

1 . 原子性(Atomicity): Java中,對(duì)基本數(shù)據(jù)類(lèi)型的讀取和賦值操作是原子性操作互站,所謂原子性操作就是指這些操作是不可中斷的私蕾,要做一定做完,要么就沒(méi)有執(zhí)行胡桃。
比如:

i = 2;j = i;i++;i = i + 1踩叭;

上面4個(gè)操作中,i=2是讀取操作,必定是原子性操作容贝,j=i你以為是原子性操作自脯,其實(shí)吧,分為兩步斤富,一是讀取i的值膏潮,然后再賦值給j,這就是2步操作了,稱(chēng)不上原子操作满力,i++i = i + 1其實(shí)是等效的焕参,讀取i的值,加1油额,再寫(xiě)回主存叠纷,那就是3步操作了。所以上面的舉例中潦嘶,最后的值可能出現(xiàn)多種情況涩嚣,就是因?yàn)闈M(mǎn)足不了原子性。

這么說(shuō)來(lái)掂僵,只有簡(jiǎn)單的讀取航厚,賦值是原子操作,還只能是用數(shù)字賦值看峻,用變量的話(huà)還多了一步讀取變量值的操作阶淘。有個(gè)例外是,虛擬機(jī)規(guī)范中允許對(duì)64位數(shù)據(jù)類(lèi)型(long和double)互妓,分為2次32為的操作來(lái)處理溪窒,但是最新JDK實(shí)現(xiàn)還是實(shí)現(xiàn)了原子操作的。

JMM只實(shí)現(xiàn)了基本的原子性冯勉,像上面i++那樣的操作澈蚌,必須借助于synchronizedLock來(lái)保證整塊代碼的原子性了。線程在釋放鎖之前灼狰,必然會(huì)把i的值刷回到主存的宛瞄。

2 . 可見(jiàn)性(Visibility):

說(shuō)到可見(jiàn)性,Java就是利用volatile來(lái)提供可見(jiàn)性的交胚。
當(dāng)一個(gè)變量被volatile修飾時(shí)份汗,那么對(duì)它的修改會(huì)立刻刷新到主存,當(dāng)其它線程需要讀取該變量時(shí)蝴簇,會(huì)去內(nèi)存中讀取新值杯活。而普通變量則不能保證這一點(diǎn)。

其實(shí)通過(guò)synchronized和Lock也能夠保證可見(jiàn)性熬词,線程在釋放鎖之前旁钧,會(huì)把共享變量值都刷回主存吸重,但是synchronized和Lock的開(kāi)銷(xiāo)都更大。

3 . 有序性(Ordering)

JMM是允許編譯器和處理器對(duì)指令重排序的歪今,但是規(guī)定了as-if-serial語(yǔ)義嚎幸,即不管怎么重排序,程序的執(zhí)行結(jié)果不能改變寄猩。比如下面的程序段:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

double pi = 3.14; //A

double r = 1; //B

double s= pi * r * r;//C

</pre>

上面的語(yǔ)句嫉晶,可以按照A->B->C執(zhí)行,結(jié)果為3.14,但是也可以按照B->A->C的順序執(zhí)行焦影,因?yàn)锳车遂、B是兩句獨(dú)立的語(yǔ)句封断,而C則依賴(lài)于A斯辰、B,所以A坡疼、B可以重排序彬呻,但是C卻不能排到A、B的前面柄瑰。JMM保證了重排序不會(huì)影響到單線程的執(zhí)行闸氮,但是在多線程中卻容易出問(wèn)題。

比如這樣的代碼:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

int a = 0;

bool flag = false;

public void write() {

a = 2;              //1

flag = true;        //2

}

public void multiply() {

if (flag) {         //3

    int ret = a * a;//4

}

}

</pre>

假如有兩個(gè)線程執(zhí)行上述代碼段教沾,線程1先執(zhí)行write蒲跨,隨后線程2再執(zhí)行multiply,最后ret的值一定是4嗎授翻?結(jié)果不一定:

image

如圖所示或悲,write方法里的1和2做了重排序,線程1先對(duì)flag賦值為true堪唐,隨后執(zhí)行到線程2巡语,ret直接計(jì)算出結(jié)果,再到線程1淮菠,這時(shí)候a才賦值為2,很明顯遲了一步男公。

這時(shí)候可以為flag加上volatile關(guān)鍵字,禁止重排序合陵,可以確保程序的“有序性”枢赔,也可以上重量級(jí)的synchronized和Lock來(lái)保證有序性,它們能保證那一塊區(qū)域里的代碼都是一次性執(zhí)行完畢的。

另外拥知,JMM具備一些先天的有序性,即不需要通過(guò)任何手段就可以保證的有序性踏拜,通常稱(chēng)為happens-before原則。<<JSR-133:Java Memory Model and Thread Specification>>定義了如下happens-before規(guī)則:

  1. 程序順序規(guī)則: 一個(gè)線程中的每個(gè)操作举庶,happens-before于該線程中的任意后續(xù)操作

  2. 監(jiān)視器鎖規(guī)則:對(duì)一個(gè)線程的解鎖执隧,happens-before于隨后對(duì)這個(gè)線程的加鎖

  3. volatile變量規(guī)則: 對(duì)一個(gè)volatile域的寫(xiě),happens-before于后續(xù)對(duì)這個(gè)volatile域的讀

  4. 傳遞性:如果A happens-before B ,且 B happens-before C, 那么 A happens-before C

  5. start()規(guī)則: 如果線程A執(zhí)行操作ThreadB_start()(啟動(dòng)線程B) , 那么A線程的ThreadB_start()happens-before 于B中的任意操作

  6. join()原則: 如果A執(zhí)行ThreadB.join()并且成功返回,那么線程B中的任意操作happens-before于線程A從ThreadB.join()操作成功返回镀琉。

  7. interrupt()原則: 對(duì)線程interrupt()方法的調(diào)用先行發(fā)生于被中斷線程代碼檢測(cè)到中斷事件的發(fā)生峦嗤,可以通過(guò)Thread.interrupted()方法檢測(cè)是否有中斷發(fā)生

  8. finalize()原則:一個(gè)對(duì)象的初始化完成先行發(fā)生于它的finalize()方法的開(kāi)始

第1條規(guī)則程序順序規(guī)則是說(shuō)在一個(gè)線程里,所有的操作都是按順序的屋摔,但是在JMM里其實(shí)只要執(zhí)行結(jié)果一樣烁设,是允許重排序的,這邊的happens-before強(qiáng)調(diào)的重點(diǎn)也是單線程執(zhí)行結(jié)果的正確性钓试,但是無(wú)法保證多線程也是如此装黑。

第2條規(guī)則監(jiān)視器規(guī)則其實(shí)也好理解,就是在加鎖之前弓熏,確定這個(gè)鎖之前已經(jīng)被釋放了恋谭,才能繼續(xù)加鎖。

第3條規(guī)則挽鞠,就適用到所討論的volatile疚颊,如果一個(gè)線程先去寫(xiě)一個(gè)變量,另外一個(gè)線程再去讀信认,那么寫(xiě)入操作一定在讀操作之前材义。

第4條規(guī)則,就是happens-before的傳遞性嫁赏。

后面幾條就不再一一贅述了其掂。

面試官:volatile關(guān)鍵字如何滿(mǎn)足并發(fā)編程的三大特性的?

那就要重提volatile變量規(guī)則: 對(duì)一個(gè)volatile域的寫(xiě)潦蝇,happens-before于后續(xù)對(duì)這個(gè)volatile域的讀款熬。
這條再拎出來(lái)說(shuō),其實(shí)就是如果一個(gè)變量聲明成是volatile的护蝶,那么當(dāng)我讀變量時(shí)华烟,總是能讀到它的最新值,這里最新值是指不管其它哪個(gè)線程對(duì)該變量做了寫(xiě)操作持灰,都會(huì)立刻被更新到主存里盔夜,我也能從主存里讀到這個(gè)剛寫(xiě)入的值。也就是說(shuō)volatile關(guān)鍵字可以保證可見(jiàn)性以及有序性堤魁。

繼續(xù)拿上面的一段代碼舉例:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

int a = 0;

bool flag = false;

public void write() {

a = 2; //1

flag = true; //2

}

public void multiply() {

if (flag) { //3

   int ret = a * a;//4

}

}

</pre>

這段代碼不僅僅受到重排序的困擾喂链,即使1、2沒(méi)有重排序妥泉。3也不會(huì)那么順利的執(zhí)行的椭微。假設(shè)還是線程1先執(zhí)行write操作,線程2再執(zhí)行multiply操作盲链,由于線程1是在工作內(nèi)存里把flag賦值為1蝇率,不一定立刻寫(xiě)回主存迟杂,所以線程2執(zhí)行時(shí),multiply再?gòu)闹鞔孀xflag值本慕,仍然可能為false排拷,那么括號(hào)里的語(yǔ)句將不會(huì)執(zhí)行。

如果改成下面這樣:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

int a = 0;

volatile bool flag = false;

public void write() {

a = 2; //1

flag = true; //2

}

public void multiply() {

if (flag) { //3

   int ret = a * a;//4

}

}

</pre>

那么線程1先執(zhí)行write,線程2再執(zhí)行multiply锅尘。根據(jù)happens-before原則监氢,這個(gè)過(guò)程會(huì)滿(mǎn)足以下3類(lèi)規(guī)則:

  1. 程序順序規(guī)則:1 happens-before 2; 3 happens-before 4; (volatile限制了指令重排序,所以1 在2 之前執(zhí)行)

  2. volatile規(guī)則:2 happens-before 3

  3. 傳遞性規(guī)則:1 happens-before 4

從內(nèi)存語(yǔ)義上來(lái)看

當(dāng)寫(xiě)一個(gè)volatile變量時(shí)藤违,JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存中的共享變量刷新到主內(nèi)存

當(dāng)讀一個(gè)volatile變量時(shí)浪腐,JMM會(huì)把該線程對(duì)應(yīng)的本地內(nèi)存置為無(wú)效,線程接下來(lái)將從主內(nèi)存中讀取共享變量顿乒。

面試官:volatile的兩點(diǎn)內(nèi)存語(yǔ)義能保證可見(jiàn)性和有序性议街,但是能保證原子性嗎?

首先我回答是不能保證原子性淆游,要是說(shuō)能保證傍睹,也只是對(duì)單個(gè)volatile變量的讀/寫(xiě)具有原子性,但是對(duì)于類(lèi)似volatile++這樣的復(fù)合操作就無(wú)能為力了犹菱,比如下面的例子:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

public class Test {

public volatile int inc = 0;

public void increase() {

    inc++;

}

public static void main(String[] args) {

    final Test test = new Test();

    for(int i=0;i<10;i++){

        new Thread(){

            public void run() {

                for(int j=0;j<1000;j++)

                    test.increase();

            };

        }.start();

    }

    while(Thread.activeCount()>1)  //保證前面的線程都執(zhí)行完

        Thread.yield();

    System.out.println(test.inc);

}

</pre>

按道理來(lái)說(shuō)結(jié)果是10000,但是運(yùn)行下很可能是個(gè)小于10000的值吮炕。有人可能會(huì)說(shuō)volatile不是保證了可見(jiàn)性啊腊脱,一個(gè)線程對(duì)inc的修改,另外一個(gè)線程應(yīng)該立刻看到傲住陕凹!可是這里的操作inc++是個(gè)復(fù)合操作啊,包括讀取inc的值鳄炉,對(duì)其自增杜耙,然后再寫(xiě)回主存。

假設(shè)線程A拂盯,讀取了inc的值為10佑女,這時(shí)候被阻塞了,因?yàn)闆](méi)有對(duì)變量進(jìn)行修改谈竿,觸發(fā)不了volatile規(guī)則团驱。

線程B此時(shí)也讀讀inc的值,主存里inc的值依舊為10空凸,做自增嚎花,然后立刻就被寫(xiě)回主存了,為11呀洲。

此時(shí)又輪到線程A執(zhí)行紊选,由于工作內(nèi)存里保存的是10啼止,所以繼續(xù)做自增,再寫(xiě)回主存兵罢,11又被寫(xiě)了一遍族壳。所以雖然兩個(gè)線程執(zhí)行了兩次increase(),結(jié)果卻只加了一次趣些。

有人說(shuō)仿荆,volatile不是會(huì)使緩存行無(wú)效的嗎?但是這里線程A讀取到線程B也進(jìn)行操作之前坏平,并沒(méi)有修改inc值拢操,所以線程B讀取的時(shí)候,還是讀的10舶替。

又有人說(shuō)令境,線程B將11寫(xiě)回主存,不會(huì)把線程A的緩存行設(shè)為無(wú)效嗎顾瞪?但是線程A的讀取操作已經(jīng)做過(guò)了啊舔庶,只有在做讀取操作時(shí),發(fā)現(xiàn)自己緩存行無(wú)效陈醒,才會(huì)去讀主存的值惕橙,所以這里線程A只能繼續(xù)做自增了。

綜上所述钉跷,在這種復(fù)合操作的情景下弥鹦,原子性的功能是維持不了了。但是volatile在上面那種設(shè)置flag值的例子里爷辙,由于對(duì)flag的讀/寫(xiě)操作都是單步的彬坏,所以還是能保證原子性的。

要想保證原子性膝晾,只能借助于synchronized,Lock以及并發(fā)包下的atomic的原子操作類(lèi)了烛恤,即對(duì)基本數(shù)據(jù)類(lèi)型的 自增(加1操作)雹熬,自減(減1操作)、以及加法操作(加一個(gè)數(shù)),減法操作(減一個(gè)數(shù))進(jìn)行了封裝干发,保證這些操作是原子性操作裳扯。

面試官:說(shuō)的還可以铜秆,那你知道volatile底層的實(shí)現(xiàn)機(jī)制誓琼?

如果把加入volatile關(guān)鍵字的代碼和未加入volatile關(guān)鍵字的代碼都生成匯編代碼,會(huì)發(fā)現(xiàn)加入volatile關(guān)鍵字的代碼會(huì)多出一個(gè)lock前綴指令巍扛。

lock前綴指令實(shí)際相當(dāng)于一個(gè)內(nèi)存屏障领跛,內(nèi)存屏障提供了以下功能:

1 . 重排序時(shí)不能把后面的指令重排序到內(nèi)存屏障之前的位置
2 . 使得本CPU的Cache寫(xiě)入內(nèi)存
3 . 寫(xiě)入動(dòng)作也會(huì)引起別的CPU或者別的內(nèi)核無(wú)效化其Cache,相當(dāng)于讓新寫(xiě)入的值對(duì)別的線程可見(jiàn)撤奸。

面試官: 你在哪里會(huì)使用到volatile吠昭,舉兩個(gè)例子呢喊括?

1. 狀態(tài)量標(biāo)記,就如上面對(duì)flag的標(biāo)記矢棚,我重新提一下:

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

int a = 0;

volatile bool flag = false;

public void write() {

a = 2;              //1

flag = true;        //2

}

public void multiply() {

if (flag) {         //3

    int ret = a * a;//4

}

}

</pre>

這種對(duì)變量的讀寫(xiě)操作郑什,標(biāo)記為volatile可以保證修改對(duì)線程立刻可見(jiàn)。比synchronized,Lock有一定的效率提升蒲肋。

2.單例模式的實(shí)現(xiàn)蘑拯,典型的雙重檢查鎖定(DCL)

<pre class="" style="margin: 0px; padding: 2px; max-width: 100%; box-sizing: inherit; overflow-wrap: normal; -webkit-tap-highlight-color: transparent; overflow-x: auto; background-color: rgb(63, 63, 63); color: rgb(220, 220, 220); border-radius: 3px; line-height: 1.4; font-size: 16px;">

class Singleton{

private volatile static Singleton instance = null;

private Singleton() {

}

public static Singleton getInstance() {

    if(instance==null) {

        synchronized (Singleton.class) {

            if(instance==null)

                instance = new Singleton();

        }

    }

    return instance;

}

}

</pre>

這是一種懶漢的單例模式,使用時(shí)才創(chuàng)建對(duì)象兜粘,而且為了避免初始化操作的指令重排序申窘,給instance加上了volatile。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末孔轴,一起剝皮案震驚了整個(gè)濱河市剃法,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌路鹰,老刑警劉巖贷洲,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異晋柱,居然都是意外死亡优构,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)趣斤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)俩块,“玉大人,你說(shuō)我怎么就攤上這事浓领。” “怎么了势腮?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵联贩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我捎拯,道長(zhǎng)泪幌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任署照,我火速辦了婚禮祸泪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘建芙。我一直安慰自己没隘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布禁荸。 她就那樣靜靜地躺著右蒲,像睡著了一般阀湿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瑰妄,一...
    開(kāi)封第一講書(shū)人閱讀 52,736評(píng)論 1 312
  • 那天陷嘴,我揣著相機(jī)與錄音,去河邊找鬼间坐。 笑死灾挨,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的竹宋。 我是一名探鬼主播劳澄,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼逝撬!你這毒婦竟也來(lái)了浴骂?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宪潮,失蹤者是張志新(化名)和其女友劉穎溯警,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體狡相,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梯轻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尽棕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喳挑。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖滔悉,靈堂內(nèi)的尸體忽然破棺而出伊诵,到底是詐尸還是另有隱情,我是刑警寧澤回官,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布曹宴,位于F島的核電站,受9級(jí)特大地震影響歉提,放射性物質(zhì)發(fā)生泄漏笛坦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一苔巨、第九天 我趴在偏房一處隱蔽的房頂上張望版扩。 院中可真熱鬧,春花似錦侄泽、人聲如沸礁芦。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宴偿。三九已至湘捎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窄刘,已是汗流浹背窥妇。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娩践,地道東北人活翩。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像翻伺,于是被迫代替她去往敵國(guó)和親材泄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

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