【并發(fā)編程系列2】synchronized鎖升級(jí)原理分析(偏向鎖-輕量級(jí)鎖-重量級(jí)鎖)

初識(shí) synchronized

在并發(fā)編程中,synchronized對(duì)我們來(lái)說(shuō)并不陌生幔嫂,我們都知道纱昧,當(dāng)多個(gè)線程并行的情況下,程序是不安全的缀去,這個(gè)不安全主要發(fā)生在共享變量的不安全侣灶,我們通過(guò)一個(gè)例子來(lái)說(shuō)明:

package com.zwx.concurrent;

public class TestSynchronized {
    private static int count;

    public static void increment(){
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        count++;

    }

    public static void main(String[] args) throws InterruptedException {
        for (int i=0;i<1000;i++){
            new Thread(()->TestSynchronized.increment()).start();
        }
        Thread.sleep(3000);
        System.out.println("結(jié)果:" + count);
    }
}

這里的輸出結(jié)果我們預(yù)期是1000,然而實(shí)際上并不一定會(huì)輸出1000缕碎,產(chǎn)生這種狀況的原因是存在如下場(chǎng)景:
1褥影、線程1獲取count為0,這時(shí)候他去執(zhí)行count++(非原子操作)
2咏雌、線程2又去獲取count,這時(shí)候因?yàn)榫€程A還沒(méi)有返回結(jié)果凡怎,所以依然獲取到0
3、線程1執(zhí)行count++后得到count=1赊抖,寫回內(nèi)存
4统倒、線程2執(zhí)行count++后得到count=1,寫回內(nèi)存
5氛雪、線程3去獲取count房匆,這時(shí)候獲取到count為1,然而實(shí)際上已經(jīng)執(zhí)行過(guò)2次count++操作了
假如線程是按照上面的1-5個(gè)步驟執(zhí)行的話,就會(huì)導(dǎo)致最后的結(jié)果不會(huì)輸出1000浴鸿,那么如何解決這個(gè)問(wèn)題呢井氢?就是在increment()方法上加上synchronized關(guān)鍵字

synchronized 用法

synchronized 有三種方式來(lái)加鎖,分別是:

  • 修飾實(shí)例方法赚楚,作用于當(dāng)前實(shí)例加鎖毙沾,進(jìn)入同步代碼前要獲得當(dāng)前實(shí)例的鎖
public synchronized void test(){
        System.out.println("修飾實(shí)例方法");
    }

  • 修飾靜態(tài)方法,作用于當(dāng)前類對(duì)象加鎖宠页,進(jìn)入同步代碼前要獲得當(dāng)前類對(duì)象的鎖
public static synchronized void test2(){
        System.out.println("修飾靜態(tài)方法");
    }

  • 修飾代碼塊左胞,指定加鎖對(duì)象,對(duì)給定對(duì)象加鎖举户,進(jìn)入同步代碼庫(kù)前要獲得給定對(duì)象的鎖
public void test3(){
        synchronized (this){
            System.out.println("修飾代碼塊");
        }
    }

鎖是如何存儲(chǔ)的

我們每個(gè)人在學(xué)習(xí)java中接觸到的最多的一句話之一我想肯定是:一切皆對(duì)象烤宙。鎖就是一個(gè)對(duì)象,那么這個(gè)對(duì)象里面的結(jié)構(gòu)是怎么樣的呢俭嘁,鎖對(duì)象里面都保存了哪些信息呢躺枕?
在Hotspot 虛擬機(jī)中,對(duì)象在內(nèi)存中的存儲(chǔ)布局供填,可以分為三個(gè)區(qū)域:對(duì)象頭(Header)拐云、實(shí)例數(shù)據(jù)(Instance Data)、對(duì)齊填充(Padding)近她。synchronized用的鎖是存在Java對(duì)象頭里的叉瘩,Java對(duì)象頭里面包含兩部分信息:
第一部分官方稱之為“Mark Word” ,用于存儲(chǔ)自身的運(yùn)行時(shí)數(shù)據(jù),如:HashCode,GC分代年齡粘捎,鎖標(biāo)記薇缅、偏向鎖線程ID等;第二部分是類型指針攒磨,即對(duì)象指向它的類元信息泳桦,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例(如果java對(duì)象是一個(gè)數(shù)組,那么對(duì)象頭中還必須有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù))
到這里我們就知道了娩缰,鎖是記錄在對(duì)象頭中的“Mark Word”灸撰,那么“Mark Word”又是如何存儲(chǔ)鎖的信息的呢?
在32位虛擬機(jī)中拼坎,“Mark Word”存儲(chǔ)結(jié)構(gòu)如下圖:

在這里插入圖片描述

在64位虛擬機(jī)中浮毯,“Mark Word”存儲(chǔ)結(jié)構(gòu)如下圖:

在這里插入圖片描述

synchronized 鎖升級(jí)

在多線程并發(fā)編程中synchronized 一直是元老級(jí)角色,很多人都會(huì)稱呼它為重量級(jí)鎖演痒。但是隨著Java SE 1.6 對(duì)synchronized 進(jìn)行了各種優(yōu)化之后,有些情況下它就并不那么重趋惨,Java SE 1.6 中為了減少獲得鎖和釋放鎖帶來(lái)的性能消耗而引入的偏向鎖和輕量級(jí)鎖鸟顺。
在Java SE 1.6中,鎖一共有4種狀態(tài),級(jí)別從低到高依次是:無(wú)鎖狀態(tài)讯嫂、偏向鎖狀態(tài)蹦锋、輕量級(jí)鎖狀態(tài)重量級(jí)鎖狀態(tài),這幾個(gè)狀態(tài)會(huì)隨著競(jìng)爭(zhēng)情況逐漸升級(jí)欧芽。至于鎖的降級(jí)并沒(méi)有一個(gè)標(biāo)準(zhǔn)莉掂,在達(dá)到一定的苛刻條件之后可以進(jìn)行降級(jí),但是一般情況我們可以簡(jiǎn)單的認(rèn)為鎖不可以降級(jí)千扔,這里不做過(guò)多的敘述憎妙。

偏向鎖

HotSpot的作者經(jīng)過(guò)研究發(fā)現(xiàn),大多數(shù)情況下曲楚,鎖不僅不存在多線程競(jìng)爭(zhēng)厘唾,而且總是由同一線程多次獲得,所以為了讓線程獲得鎖的代價(jià)更低而引入了偏向鎖龙誊。
當(dāng)一個(gè)線程訪問(wèn)加了同步鎖的代碼塊時(shí)抚垃,會(huì)在對(duì)象頭中存儲(chǔ)當(dāng)前線程的 ID,后續(xù)這個(gè)線程進(jìn)入和退出這段加了同步鎖的代碼塊時(shí)趟大,不需要再次加鎖和釋放鎖鹤树。而是直接比較對(duì)象頭里面是否存儲(chǔ)了指向當(dāng)前線程的線程ID。如果相等表示偏向鎖是偏向于當(dāng)前線程的逊朽,就不需要再嘗試獲得鎖了罕伯。

偏向鎖的獲取

1、首先獲取鎖對(duì)象頭中的 Mark Word惋耙,判斷當(dāng)前對(duì)象是否處于可偏向狀態(tài)(即當(dāng)前沒(méi)有對(duì)象獲得偏向鎖)捣炬。
2、如果是可偏向狀態(tài)绽榛,則通過(guò)CAS原子操作湿酸,把當(dāng)前線程的ID寫入到 MarkWord,如果CAS成功灭美,表示獲得偏向鎖成功推溃,會(huì)將偏向鎖標(biāo)記設(shè)置為1,且將當(dāng)前線程的ID寫入Mark Word届腐;如果CAS失敗則說(shuō)明當(dāng)前有其他線程獲得了偏向鎖铁坎,同時(shí)也說(shuō)明當(dāng)前環(huán)境存在鎖競(jìng)爭(zhēng),這時(shí)候就需要將已獲得偏向鎖的線程中的偏向鎖撤銷掉(具體參考下面偏向鎖的撤銷)犁苏,并升級(jí)為輕量級(jí)鎖硬萍。
3、如果當(dāng)前線程是已偏向狀態(tài)围详,需要檢查Mark Word中的ThreadID是否和自己相等朴乖,如果相等則不需要再次獲得鎖祖屏,可以直接執(zhí)行同步代碼塊,如果不相等买羞,說(shuō)明當(dāng)前偏向的是其他線程袁勺,需要撤銷偏向鎖并升級(jí)到輕量級(jí)鎖。

偏向鎖的撤銷

偏向鎖的撤銷畜普,需要等待全局安全點(diǎn)(即在這個(gè)時(shí)間點(diǎn)上沒(méi)有正在執(zhí)行的字節(jié)碼)期丰,然后會(huì)暫停擁有偏向鎖的線程,并檢查持有偏向鎖的線程是否活著吃挑,主要有以下兩種情況:

  1. 如果線程不處于活動(dòng)狀態(tài)钝荡,則將對(duì)象頭設(shè)置成無(wú)鎖狀態(tài)。
  2. 如果線程仍然活著儒鹿,擁有偏向鎖的棧會(huì)被執(zhí)行化撕,遍歷偏向?qū)ο蟮逆i記錄,棧中的鎖記錄和對(duì)象頭的Mark Word要么重新偏向于其他線程(重偏向需要滿足批量重偏向的條件)约炎,要么恢復(fù)到無(wú)鎖或者標(biāo)記對(duì)象不適合作為偏向鎖植阴。

最后喚醒暫停的線程。

偏向鎖的批量重偏向

一個(gè)線程創(chuàng)建了大量對(duì)象而且執(zhí)行了同步操作后另一個(gè)線程又來(lái)將這些對(duì)象作為鎖對(duì)象進(jìn)行操作圾浅,并且達(dá)到閾值掠手,此時(shí)就會(huì)發(fā)生偏向鎖重偏向的操作(除了這種情況,其他情況只有有線程來(lái)競(jìng)爭(zhēng)鎖狸捕,則偏向鎖狀態(tài)就結(jié)束了)喷鸽。
-XX:BiasedLockingBulkRebiasThreshold 為重偏向閾值JVM參數(shù),默認(rèn)20灸拍,可以通過(guò)-XX:+PrintFlagsFinal打印出默認(rèn)參數(shù)做祝,接下來(lái)我們通過(guò)一個(gè)示例來(lái)演示一下批量重偏向:

<dependency>
     <groupId>org.openjdk.jol</groupId>
     <artifactId>jol-core</artifactId>
     <version>0.10</version>
 </dependency>

package com.zwx.concurrent;

import com.zwx.model.User;
import org.openjdk.jol.info.ClassLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class BiasedLockDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread.sleep(5000);//默認(rèn)延遲4s才會(huì)開(kāi)啟偏向鎖,休眠5s確保開(kāi)啟偏向鎖

        List<User> list = new ArrayList<>();
        new Thread(()->{
            for (int i=0;i<20;i++){
                //這里必須要new不同的對(duì)象鸡岗,不能共用同一個(gè)對(duì)象
                User user = new User();//只是一個(gè)空對(duì)象
                synchronized (user){
                    list.add(user);
                    System.out.println("t1線程第" + (i+1) + "對(duì)象:" + ClassLayout.parseInstance(user).toPrintable());
                }
            }
        },"t1").start();

        try {
            Thread.sleep(10000);//確保t1創(chuàng)建對(duì)象完畢
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("------------------------------------------------------");
        new Thread(()->{
            for (int j=0;j<20;j++){
                User user = list.get(j);
                synchronized (user){
                    System.out.println("t2線程第" + (j+1) + "對(duì)象:" + ClassLayout.parseInstance(user).toPrintable());
                }
            }
        },"t2").start();
    }
}

運(yùn)行結(jié)果部分截圖(t1線程肯定是101混槐,就不截圖了,t2前面19個(gè)都是000轩性,第20個(gè)達(dá)到閾值了声登,發(fā)生了重偏向):
101三位數(shù)說(shuō)明:
第一位:0-表示非偏向 1-表示偏向
后兩位:00-表示輕量級(jí)鎖 01-表示偏向鎖 10表示重量級(jí)鎖


在這里插入圖片描述

當(dāng)然,有批量重偏向揣苏,也有批量撤銷悯嗓,在這里就不做過(guò)多敘述,以后有時(shí)間了可以單獨(dú)更深入的寫一寫卸察,感興趣的可以關(guān)注留意脯厨!

偏向鎖及撤銷流程圖

在這里插入圖片描述

偏向鎖注意事項(xiàng)

偏向鎖在Java SE 1.6和Java SE 1.7里是默認(rèn)啟用的,但是它在應(yīng)用程序啟動(dòng)幾秒鐘之后才激活坑质,如有必要可以使用JVM參數(shù)來(lái)關(guān)閉延遲:-XX:BiasedLockingStartupDelay=0合武。如果你確定應(yīng)用程序里所有的鎖通常情況下都處于競(jìng)爭(zhēng)狀態(tài)个少,可以通過(guò)JVM參數(shù)關(guān)閉偏向鎖:-XX:- UseBiasedLocking=false,那么程序默認(rèn)會(huì)進(jìn)入輕量級(jí)鎖狀態(tài)眯杏。
如果我們的應(yīng)用中大多數(shù)情況存在線程競(jìng)爭(zhēng),那么建議是關(guān)閉偏向鎖壳澳,因?yàn)殚_(kāi)啟反而會(huì)因?yàn)槠蜴i撤銷操作而引起更多的資源消耗岂贩。

輕量級(jí)鎖

輕量級(jí)鎖,一般用于兩個(gè)線程在交替使用鎖的時(shí)候,由于沒(méi)有同時(shí)搶鎖巷波,屬于一種比較和諧的狀態(tài)萎津,就可以使用輕量級(jí)鎖。

輕量級(jí)鎖加鎖

線程在執(zhí)行同步代碼塊之前抹镊,JVM會(huì)先在當(dāng)前線程的棧楨中創(chuàng)建用于存儲(chǔ)鎖記錄的空間锉屈,并將對(duì)象頭中的Mark Word復(fù)制到鎖記錄中,官方稱為Displaced Mark Word垮耳。然后線程嘗試使用 CAS將對(duì)象頭中的Mark Word替換為指向鎖記錄的指針颈渊。如果成功,當(dāng)前線程獲得鎖终佛,如果失敗俊嗽,表示其他線程競(jìng)爭(zhēng)鎖,當(dāng)前線程便嘗試使用自旋來(lái)獲取鎖铃彰。

輕量級(jí)鎖解鎖

輕量級(jí)解鎖時(shí)绍豁,會(huì)使用原子的CAS操作將Displaced Mark Word替換回到對(duì)象頭,如果成功牙捉,則表示沒(méi)有競(jìng)爭(zhēng)發(fā)生竹揍。如果失敗,表示當(dāng)前鎖存在競(jìng)爭(zhēng)邪铲,鎖就會(huì)膨脹成重量級(jí)鎖

輕量級(jí)鎖及膨脹流程圖

在這里插入圖片描述

自旋鎖

輕量級(jí)鎖在加鎖過(guò)程中芬位,用到了自旋鎖。所謂自旋霜浴,就是指當(dāng)有另外一個(gè)線程來(lái)競(jìng)爭(zhēng)鎖時(shí)晶衷,這個(gè)線程會(huì)在原地循環(huán)等待,而不是把該線程給阻塞阴孟,直到那個(gè)獲得鎖的線程釋放鎖之后晌纫,這個(gè)線程就可以馬上獲得鎖的。
為什么要采用自旋等待呢永丝?
因?yàn)榻^大多數(shù)情況下線程獲得鎖和釋放鎖的過(guò)程都是非常短暫的锹漱,自旋一定次數(shù)之后極有可能碰到獲得鎖的線程釋放鎖,所以慕嚷,輕量級(jí)鎖適用于那些同步代碼塊執(zhí)行很快的場(chǎng)景哥牍,這樣毕泌,線程原地等待很短的時(shí)間就能夠獲得鎖了。
注意:鎖在原地循環(huán)等待的時(shí)候嗅辣,是會(huì)消耗CPU資源的撼泛。所以自旋必須要有一定的條件控制,否則如果一個(gè)線程執(zhí)行同步代碼塊的時(shí)間很長(zhǎng)澡谭,那么等待鎖的線程會(huì)不斷的循環(huán)反而會(huì)消耗CPU資源愿题。默認(rèn)情況下鎖自旋的次數(shù)是 10 次,可以使用-XX:PreBlockSpin參數(shù)來(lái)設(shè)置自旋鎖等待的次數(shù)蛙奖。

自適應(yīng)自旋

在 JDK1.7 開(kāi)始潘酗,引入了自適應(yīng)自旋鎖,修改自旋鎖次數(shù)的JVM參數(shù)被取消雁仲,虛擬機(jī)不再支持由用戶配置自旋鎖次數(shù)仔夺,而是由虛擬機(jī)自動(dòng)調(diào)整。自適應(yīng)意味著自旋的次數(shù)不是固定不變的攒砖,而是根據(jù)前一次在同一個(gè)鎖上自旋的時(shí)間以及鎖的擁有者的狀態(tài)來(lái)決定缸兔。如果在同一個(gè)鎖對(duì)象上,自旋等待剛剛成功獲得過(guò)鎖吹艇,并且持有鎖的線程正在運(yùn)行中灶体,那么虛擬機(jī)就會(huì)認(rèn)為這次自旋也是很有可能再次成功,進(jìn)而它將允許自旋等待持續(xù)相對(duì)更長(zhǎng)的時(shí)間掐暮。如果對(duì)于某個(gè)鎖蝎抽,自旋很少成功獲得過(guò),那在以后嘗試獲取這個(gè)鎖時(shí)將可能省略掉自旋過(guò)程路克,直接阻塞線程樟结,避免浪費(fèi)處理器資源。

重量級(jí)鎖

當(dāng)輕量級(jí)鎖膨脹到重量級(jí)鎖之后精算,意味著線程只能被掛起阻塞來(lái)等待喚醒了瓢宦。每一個(gè)對(duì)象中都有一個(gè)Monitor監(jiān)視器,而Monitor依賴操作系統(tǒng)的 MutexLock(互斥鎖)來(lái)實(shí)現(xiàn)的, 線程被阻塞后便進(jìn)入內(nèi)核(Linux)調(diào)度狀態(tài)灰羽,這個(gè)會(huì)導(dǎo)致系統(tǒng)在用戶態(tài)與內(nèi)核態(tài)之間來(lái)回切換驮履,嚴(yán)重影響鎖的性能。
monitorenter指令是在編譯后插入到同步代碼塊的開(kāi)始位置廉嚼,而monitorexit是插入到方法結(jié)束處和異常處玫镐,JVM要保證每個(gè)monitorenter必須有對(duì)應(yīng)的monitorexit與之配對(duì)。而且當(dāng)一個(gè)monitor被持有后怠噪,它將處于鎖定狀態(tài)恐似。線程執(zhí)行到monitorenter指令時(shí),將會(huì)嘗試獲取對(duì)象所對(duì)應(yīng)的monitor的所有權(quán)傍念,即嘗試獲得對(duì)象的鎖矫夷。我們可以簡(jiǎn)單的理解為葛闷,在加重量級(jí)鎖的時(shí)候會(huì)執(zhí)行monitorenter指令,解鎖時(shí)會(huì)執(zhí)行monitorexit指令双藕。

鎖的優(yōu)缺點(diǎn)對(duì)比

優(yōu)點(diǎn) 缺點(diǎn) 適用場(chǎng)景
偏向鎖 加鎖和解鎖不需要額外的消耗淑趾,和執(zhí)行非同步代碼塊僅存在納秒級(jí)差距 如果線程間存在鎖競(jìng)爭(zhēng),會(huì)帶來(lái)額外的鎖撤銷消耗 適用于只有一個(gè)線程訪問(wèn)同步代碼塊場(chǎng)景
輕量級(jí)鎖 競(jìng)爭(zhēng)的線程不會(huì)阻塞忧陪,提高了程序的響應(yīng)速度 如果始終得不到鎖治笨,使用自旋會(huì)消耗CPU 追求響應(yīng)時(shí)間;同步代碼塊執(zhí)行時(shí)間非常短
重量級(jí)鎖 線程競(jìng)爭(zhēng)不使用自旋赤嚼,不會(huì)消耗CPU 線程阻塞,響應(yīng)時(shí)間緩慢 追求吞吐量顺又;同步代碼塊執(zhí)行時(shí)間較長(zhǎng)

總結(jié)

synchronized可以解決并發(fā)編程中的三大問(wèn)題:原子性更卒,可見(jiàn)性有序性,雖然JDK對(duì)其做了優(yōu)化稚照,有些時(shí)候并不那么重了蹂空,但是在某些場(chǎng)景中,我們可以使用[volatile關(guān)鍵字]代替synchronized果录,如果volatile變量修飾符使用恰當(dāng)?shù)脑捝险恚萻ynchronized的使用和執(zhí)行成本更低,因?yàn)樗粫?huì)引起線程上下文的切換和調(diào)度弱恒。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辨萍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子返弹,更是在濱河造成了極大的恐慌锈玉,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件义起,死亡現(xiàn)場(chǎng)離奇詭異拉背,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)默终,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門椅棺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人齐蔽,你說(shuō)我怎么就攤上這事两疚。” “怎么了含滴?”我有些...
    開(kāi)封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵鬼雀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蛙吏,道長(zhǎng)源哩,這世上最難降的妖魔是什么鞋吉? 我笑而不...
    開(kāi)封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮励烦,結(jié)果婚禮上谓着,老公的妹妹穿的比我還像新娘。我一直安慰自己坛掠,他們只是感情好赊锚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著屉栓,像睡著了一般舷蒲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上友多,一...
    開(kāi)封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天牲平,我揣著相機(jī)與錄音,去河邊找鬼域滥。 笑死纵柿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的启绰。 我是一名探鬼主播昂儒,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼委可!你這毒婦竟也來(lái)了渊跋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤着倾,失蹤者是張志新(化名)和其女友劉穎刹枉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體屈呕,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡微宝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虎眨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蟋软。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嗽桩,靈堂內(nèi)的尸體忽然破棺而出岳守,到底是詐尸還是另有隱情,我是刑警寧澤碌冶,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布湿痢,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏譬重。R本人自食惡果不足惜拒逮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望臀规。 院中可真熱鬧滩援,春花似錦、人聲如沸塔嬉。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谨究。三九已至恩袱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胶哲,已是汗流浹背畔塔。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纪吮,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓萎胰,卻偏偏與公主長(zhǎng)得像碾盟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子技竟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349