IllegalMonitorStateException 異常 與 Java中的"對(duì)象監(jiān)視器Monitor"和"對(duì)象鎖"詳解

異常解析

在線程中調(diào)用wait方法的時(shí)候要用synchronized鎖住對(duì)象陆淀,確保代碼段不會(huì)被多個(gè)線程調(diào)用。

如果沒有synchronized加鎖系吩,那么當(dāng)前的線程不是此對(duì)象監(jiān)視器的所有者, 就會(huì)拋出 IllegalMonitorStateException 異常信息玖姑。

當(dāng)前線程要鎖定該對(duì)象之后社付,才能用鎖定的對(duì)象執(zhí)行這些方法,這里需要用到synchronized關(guān)鍵字燃箭,鎖定哪個(gè)對(duì)象就用哪個(gè)對(duì)象來執(zhí)行 notify(), notifyAll(),wait(), wait(long), wait(long, int) 操作冲呢,否則就會(huì)報(bào)IllegalMonitorStateException異常。

在JVM中招狸,每個(gè)對(duì)象和類在邏輯上都是和一個(gè)監(jiān)視器相關(guān)聯(lián)的敬拓。為了實(shí)現(xiàn)監(jiān)視器的排他性監(jiān)視能力,JVM為每一個(gè)對(duì)象和類都關(guān)聯(lián)一個(gè)鎖裙戏。鎖住了一個(gè)對(duì)象乘凸,就是獲得對(duì)象相關(guān)聯(lián)的監(jiān)視器。

監(jiān)視器好比一做建筑,它有一個(gè)很特別的房間,房間里有一些數(shù)據(jù),而且在同一時(shí)間只能被一個(gè)線程占據(jù),進(jìn)入這個(gè)建筑叫做"進(jìn)入監(jiān)視器",進(jìn)入建筑中的那個(gè)特別的房間叫做"獲得監(jiān)視器",占據(jù)房間叫做"持有監(jiān)視器",離開房間叫做"釋放監(jiān)視器",離開建筑叫做"退出監(jiān)視器"累榜。

而一個(gè)鎖就像一種任何時(shí)候只允許一個(gè)線程擁有的特權(quán)营勤。一個(gè)線程可以允許多次對(duì)同一對(duì)象上鎖.對(duì)于每一個(gè)對(duì)象來說,java虛擬機(jī)維護(hù)一個(gè)計(jì)數(shù)器,記錄對(duì)象被加了多少次鎖,沒被鎖的對(duì)象的計(jì)數(shù)器是0,線程每加鎖一次,計(jì)數(shù)器就加1,每釋放一次,計(jì)數(shù)器就減1.當(dāng)計(jì)數(shù)器跳到0的時(shí)候,鎖就被完全釋放了。

Java虛擬機(jī)中的一個(gè)線程在它到達(dá)監(jiān)視區(qū)域開始處的時(shí)候請(qǐng)求一個(gè)鎖.JAVA程序中每一個(gè)監(jiān)視區(qū)域都和一個(gè)對(duì)象引用相關(guān)聯(lián). 在java中壹罚,synchronized是唯一實(shí)現(xiàn)同步的東西葛作。

Java對(duì)象的組成與鎖的狀態(tài)

HotSpot虛擬機(jī)中,對(duì)象在內(nèi)存中存儲(chǔ)的布局可以分為三塊區(qū)域:

  • 對(duì)象頭(Header)
  • 實(shí)例數(shù)據(jù)(Instance Data)和
  • 對(duì)齊填充(Padding)

HotSpot虛擬機(jī)的對(duì)象頭(Object Header)包括兩部分信息渔嚷,第一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù)进鸠, 如哈希碼(HashCode)、GC分代年齡形病、鎖狀態(tài)標(biāo)志客年、線程持有的鎖霞幅、偏向線程ID、偏向時(shí)間戳等等量瓜,這部分?jǐn)?shù)據(jù)的長度在32位和64位的虛擬機(jī)(暫 不考慮開啟壓縮指針的場(chǎng)景)中分別為32個(gè)和64個(gè)Bits司恳,官方稱它為“Mark Word”。

對(duì)象需要存儲(chǔ)的運(yùn)行時(shí)數(shù)據(jù)很多绍傲,其實(shí)已經(jīng)超出了32扔傅、64位Bitmap結(jié)構(gòu)所能記錄的限度,但是對(duì)象頭信息是與對(duì)象自身定義的數(shù)據(jù)無關(guān)的額 外存儲(chǔ)成本烫饼,考慮到虛擬機(jī)的空間效率猎塞,Mark Word被設(shè)計(jì)成一個(gè)非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小的空間內(nèi)存儲(chǔ)盡量多的信息,它會(huì)根據(jù)對(duì)象的狀態(tài)復(fù)用自己的存儲(chǔ)空間杠纵。例如在32位的HotSpot虛擬機(jī) 中對(duì)象未被鎖定的狀態(tài)下荠耽,Mark Word的32個(gè)Bits空間中的25Bits用于存儲(chǔ)對(duì)象哈希碼(HashCode),4Bits用于存儲(chǔ)對(duì)象分代年齡比藻,2Bits用于存儲(chǔ)鎖標(biāo)志 位铝量,1Bit固定為0,在其他狀態(tài)(輕量級(jí)鎖定银亲、重量級(jí)鎖定慢叨、GC標(biāo)記、可偏向)下對(duì)象的存儲(chǔ)內(nèi)容如下表所示务蝠。

鎖的狀態(tài)總共有四種:無鎖狀態(tài)拍谐、偏向鎖、輕量級(jí)鎖和重量級(jí)鎖请梢。隨著鎖的競爭赠尾,鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)的重量級(jí)鎖(但是鎖的升級(jí)是單向的毅弧,也就是說只能從低到高升級(jí)气嫁,不會(huì)出現(xiàn)鎖的降級(jí))。JDK 1.6中默認(rèn)是開啟偏向鎖和輕量級(jí)鎖的够坐,我們也可以通過-XX:-UseBiasedLocking來禁用偏向鎖寸宵。

Mark Word

Mark Word記錄了對(duì)象和鎖有關(guān)的信息,當(dāng)這個(gè)對(duì)象被synchronized關(guān)鍵字當(dāng)成同步鎖時(shí)元咙,圍繞這個(gè)鎖的一系列操作都和Mark Word有關(guān)梯影。

Mark Word在32位JVM中的長度是32bit,在64位JVM中長度是64bit庶香。

Mark Word在不同的鎖狀態(tài)下存儲(chǔ)的內(nèi)容不同甲棍,在32位JVM中是這么存的:

其中無鎖和偏向鎖的鎖標(biāo)志位都是01,只是在前面的1bit區(qū)分了這是無鎖狀態(tài)還是偏向鎖狀態(tài)赶掖。

JDK1.6以后的版本在處理同步鎖時(shí)存在鎖升級(jí)的概念感猛,JVM對(duì)于同步鎖的處理是從偏向鎖開始的七扰,隨著競爭越來越激烈,處理方式從偏向鎖升級(jí)到輕量級(jí)鎖陪白,最終升級(jí)到重量級(jí)鎖颈走。

JVM一般是這樣使用鎖和Mark Word的:

1,當(dāng)沒有被當(dāng)成鎖時(shí)咱士,這就是一個(gè)普通的對(duì)象立由,Mark Word記錄對(duì)象的HashCode,鎖標(biāo)志位是01序厉,是否偏向鎖那一位是0锐膜。

2,當(dāng)對(duì)象被當(dāng)做同步鎖并有一個(gè)線程A搶到了鎖時(shí)脂矫,鎖標(biāo)志位還是01枣耀,但是否偏向鎖那一位改成1霉晕,前23bit記錄搶到鎖的線程id庭再,表示進(jìn)入偏向鎖狀態(tài)。

3牺堰,當(dāng)線程A再次試圖來獲得鎖時(shí)拄轻,JVM發(fā)現(xiàn)同步鎖對(duì)象的標(biāo)志位是01,是否偏向鎖是1伟葫,也就是偏向狀態(tài)恨搓,Mark Word中記錄的線程id就是線程A自己的id,表示線程A已經(jīng)獲得了這個(gè)偏向鎖筏养,可以執(zhí)行同步鎖的代碼斧抱。

4,當(dāng)線程B試圖獲得這個(gè)鎖時(shí)渐溶,JVM發(fā)現(xiàn)同步鎖處于偏向狀態(tài)辉浦,但是Mark Word中的線程id記錄的不是B,那么線程B會(huì)先用CAS操作試圖獲得鎖茎辐,這里的獲得鎖操作是有可能成功的宪郊,因?yàn)榫€程A一般不會(huì)自動(dòng)釋放偏向鎖。如果搶鎖成功拖陆,就把Mark Word里的線程id改為線程B的id弛槐,代表線程B獲得了這個(gè)偏向鎖,可以執(zhí)行同步鎖代碼依啰。如果搶鎖失敗乎串,則繼續(xù)執(zhí)行步驟5。

5速警,偏向鎖狀態(tài)搶鎖失敗叹誉,代表當(dāng)前鎖有一定的競爭艰争,偏向鎖將升級(jí)為輕量級(jí)鎖。JVM會(huì)在當(dāng)前線程的線程棧中開辟一塊單獨(dú)的空間桂对,里面保存指向?qū)ο箧iMark Word的指針甩卓,同時(shí)在對(duì)象鎖Mark Word中保存指向這片空間的指針。上述兩個(gè)保存操作都是CAS操作蕉斜,如果保存成功逾柿,代表線程搶到了同步鎖,就把Mark Word中的鎖標(biāo)志位改成00宅此,可以執(zhí)行同步鎖代碼机错。如果保存失敗,表示搶鎖失敗父腕,競爭太激烈弱匪,繼續(xù)執(zhí)行步驟6。

6璧亮,輕量級(jí)鎖搶鎖失敗萧诫,JVM會(huì)使用自旋鎖,自旋鎖不是一個(gè)鎖狀態(tài)枝嘶,只是代表不斷的重試帘饶,嘗試搶鎖。從JDK1.7開始群扶,自旋鎖默認(rèn)啟用及刻,自旋次數(shù)由JVM決定。如果搶鎖成功則執(zhí)行同步鎖代碼竞阐,如果失敗則繼續(xù)執(zhí)行步驟7缴饭。

7,自旋鎖重試之后如果搶鎖依然失敗骆莹,同步鎖會(huì)升級(jí)至重量級(jí)鎖颗搂,鎖標(biāo)志位改為10。在這個(gè)狀態(tài)下汪疮,未搶到鎖的線程都會(huì)被阻塞峭火。

指向類的指針

該指針在32位JVM中的長度是32bit,在64位JVM中長度是64bit智嚷。

Java對(duì)象的類數(shù)據(jù)保存在方法區(qū)卖丸。

數(shù)組長度

只有數(shù)組對(duì)象保存了這部分?jǐn)?shù)據(jù)。

該數(shù)據(jù)在32位和64位JVM中長度都是32bit盏道。

實(shí)例數(shù)據(jù)

對(duì)象的實(shí)例數(shù)據(jù)就是在java代碼中能看到的屬性和他們的值稍浆。

對(duì)齊填充字節(jié)

因?yàn)镴VM要求java的對(duì)象占的內(nèi)存大小應(yīng)該是8bit的倍數(shù),所以后面有幾個(gè)字節(jié)用于把對(duì)象的大小補(bǔ)齊至8bit的倍數(shù),沒有特別的功能衅枫。

Java對(duì)象的Monitor機(jī)制

Monitor的機(jī)制分析

Java虛擬機(jī)給每個(gè)對(duì)象和class字節(jié)碼都設(shè)置了一個(gè)監(jiān)聽器Monitor嫁艇,用于檢測(cè)并發(fā)代碼的重入,同時(shí)在Object類中還提供了notify和wait方法來對(duì)線程進(jìn)行控制弦撩。

在java.lang.Object類中有如下代碼:

public class Object {
    ...
    private transient int shadow$_monitor_;
    public final native void notify();
    public final native void notifyAll();
    public final native void wait() throws InterruptedException;
    public final void wait(long millis) throws InterruptedException {
        wait(millis, 0);
    }
    public final native void wait(long millis, int nanos) throws InterruptedException;
    ...
}

Monitor的機(jī)制如下圖:

結(jié)合上圖來分析Object的Monitor機(jī)制步咪。

Monitor可以類比為一個(gè)特殊的房間,這個(gè)房間中有一些被保護(hù)的數(shù)據(jù)益楼,Monitor保證每次只能有一個(gè)線程能進(jìn)入這個(gè)房間進(jìn)行訪問被保護(hù)的數(shù)據(jù)猾漫,進(jìn)入房間即為持有Monitor,退出房間即為釋放Monitor感凤。

當(dāng)一個(gè)線程需要訪問受保護(hù)的數(shù)據(jù)(即需要獲取對(duì)象的Monitor)時(shí)悯周,它會(huì)首先在entry-set入口隊(duì)列中排隊(duì)(這里并不是真正的按照排隊(duì)順序),如果沒有其他線程正在持有對(duì)象的Monitor陪竿,那么它會(huì)和entry-set隊(duì)列和wait-set隊(duì)列中的被喚醒的其他線程進(jìn)行競爭(即通過CPU調(diào)度)禽翼,選出一個(gè)線程來獲取對(duì)象的Monitor,執(zhí)行受保護(hù)的代碼段族跛,執(zhí)行完畢后釋放Monitor闰挡,如果已經(jīng)有線程持有對(duì)象的Monitor,那么需要等待其釋放Monitor后再進(jìn)行競爭庸蔼。

再說一下wait-set隊(duì)列解总。當(dāng)一個(gè)線程擁有Monitor后,經(jīng)過某些條件的判斷(比如用戶取錢發(fā)現(xiàn)賬戶沒錢)姐仅,這個(gè)時(shí)候需要調(diào)用Object的wait方法,線程就釋放了Monitor刻盐,進(jìn)入wait-set隊(duì)列掏膏,等待Object的notify方法(比如用戶向賬戶里面存錢)。當(dāng)該對(duì)象調(diào)用了notify方法或者notifyAll方法后敦锌,wait-set中的線程就會(huì)被喚醒馒疹,然后在wait-set隊(duì)列中被喚醒的線程和entry-set隊(duì)列中的線程一起通過CPU調(diào)度來競爭對(duì)象的Monitor,最終只有一個(gè)線程能獲取對(duì)象的Monitor乙墙。

需要注意的是:

當(dāng)一個(gè)線程在wait-set中被喚醒后颖变,并不一定會(huì)立刻獲取Monitor,它需要和其他線程去競爭;
如果一個(gè)線程是從wait-set隊(duì)列中喚醒后听想,獲取到的Monitor腥刹,它會(huì)去讀取它自己保存的PC計(jì)數(shù)器中的地址谭企,從它調(diào)用wait方法的地方開始執(zhí)行纺阔。

Monitor機(jī)制在Java中是如何實(shí)現(xiàn)的呢?

即通過synchronized關(guān)鍵字實(shí)現(xiàn)線程同步來獲取對(duì)象的Monitor症昏。synchronized同步分為以下兩種方式:

同步代碼塊:

synchronized(Obejct obj) {
    //同步代碼塊
    ...
}

上述代碼表示在進(jìn)入同步代碼塊之前,先要去獲取obj的Monitor垫卤,如果已經(jīng)被其他線程獲取了威彰,那么當(dāng)前線程必須等待直至其他線程釋放obj的Monitor

這里的obj可以是類.class,表示需要去獲取該類的字節(jié)碼的Monitor穴肘,獲取后歇盼,其他線程無法再去獲取到class字節(jié)碼的Monitor了,即無法訪問屬于類的同步的靜態(tài)方法了评抚,但是對(duì)于對(duì)象的實(shí)例方法的訪問不受影響

同步方法:

public class Test {

    public static Test instance;
    public int val;

    public synchronized void set(int val) {
        this.val = val;
    }

    public static synchronized void set(Test instance) {
        Test.instance = instance;
    }

}

上述使用了synchronized分別修飾了非靜態(tài)方法和靜態(tài)方法旺遮。

  • 非靜態(tài)方法可以理解為,需要獲取當(dāng)前對(duì)象this的Monitor盈咳,獲取后耿眉,其他需要獲取該對(duì)象的Monitor的線程會(huì)被堵塞。

  • 靜態(tài)方法可以理解為鱼响,需要獲取該類字節(jié)碼的Monitor(因?yàn)閟tatic方法不屬于任何對(duì)象鸣剪,而是屬于類的方法),獲取后丈积,其他需要獲取字節(jié)碼的Monitor的線程會(huì)被堵塞筐骇。

Object的notify方法和wait方法詳解

上面在講述Monitor機(jī)制的時(shí)候已經(jīng)分析了notify和wait的用法,這里具體分析下江滨。

wait方法

wait有三個(gè)重載方法铛纬,分別如下:

public final void wait() throws InterruptedException;
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException;

后面兩個(gè)傳入了時(shí)間參數(shù)(nanos表示納秒),表示如果指定時(shí)間過去還沒有其他線程調(diào)用notify或者notifyAll方法來將其喚醒唬滑,那么該線程會(huì)自動(dòng)被喚醒告唆。

調(diào)用obj.wait方法需要注意的是,當(dāng)前線程必須獲取到了obj的Monitor(The current thread must own this object's monitor)晶密,才能去調(diào)用其wait方法擒悬,即wait必須放在同步方法或同步代碼塊中。

調(diào)用的是obj.wait()稻艰,而不是Thread.currentThread.wait()懂牧。

notify() 方法

    /**
     * Wakes up a single thread that is waiting on this object's
     * monitor. If any threads are waiting on this object, one of them
     * is chosen to be awakened. 
     * ...
     * Only one thread at a time can own an object's monitor.
     *
     * @throws  IllegalMonitorStateException  if the current thread is not
     *               the owner of this object's monitor.
     * @see        java.lang.Object#notifyAll()
     * @see        java.lang.Object#wait()
     */
    public final native void notify();

notify有兩個(gè)方法notify和notifyAll,前者只能喚醒一個(gè)正在等待這個(gè)對(duì)象的monitor的線程尊勿,具體由JVM決定僧凤,后者則會(huì)喚醒所有正在等待這個(gè)對(duì)象的monitor的線程

需要關(guān)注的點(diǎn):

調(diào)用notify方法,并不意味著釋放了Monitor元扔,必須要等同步代碼塊結(jié)束后才會(huì)釋放Monitor躯保。

在調(diào)用notify方法時(shí),必須保證其他線程處于wait狀態(tài)摇展,否則調(diào)用notify沒有任何效果吻氧,導(dǎo)致之后其他線程永遠(yuǎn)處于堵塞狀態(tài)溺忧。


notify()

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

喚醒正在此對(duì)象監(jiān)視器上等待的單個(gè)線程。如果有任何線程正在等待這個(gè)對(duì)象盯孙,那么將選擇喚醒其中的一個(gè)線程鲁森。這個(gè)選擇是任意的,由實(shí)現(xiàn)決定振惰。線程通過調(diào)用其中一個(gè)等待方法來等待對(duì)象的監(jiān)視器歌溉。

The awakened thread will not be able to proceed until the current thread relinquishes(釋放) the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

被喚醒的線程將無法繼續(xù)前進(jìn),直到當(dāng)前線程釋放該對(duì)象上的鎖骑晶。被喚醒的線程將以通常的方式與其他線程競爭痛垛,這些線程可能正在積極地對(duì)這個(gè)對(duì)象進(jìn)行同步; 例如,在成為下一個(gè)鎖定此對(duì)象的線程時(shí)桶蛔,被喚醒的線程沒有任何特權(quán)或不利條件匙头。

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

  • By executing a synchronized instance method of that object.
  • By executing the body of a synchronized statement that synchronizes on the object.

此方法只能由此對(duì)象監(jiān)視器的所有者的線程調(diào)用。線程通過以下三種方式之一成為對(duì)象監(jiān)視器的所有者:

  • 通過執(zhí)行該對(duì)象的同步實(shí)例方法仔雷。
  • 通過執(zhí)行同步語句的主體對(duì)對(duì)象進(jìn)行同步蹂析。

For objects of type Class, by executing a synchronized static method of that class.
Only one thread at a time can own an object's monitor.

對(duì)于Class類型的對(duì)象,通過執(zhí)行該類的同步靜態(tài)方法碟婆。
每次只有一個(gè)線程可以擁有一個(gè)對(duì)象的監(jiān)視器电抚。

Throws:

IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.

See Also:

notifyAll(), wait()

小結(jié)

java中每個(gè)對(duì)象都有唯一的一個(gè)monitor,想擁有一個(gè)對(duì)象的monitor的話有以下三種方式:

1.執(zhí)行該對(duì)象的同步方法

public synchronize a () {
}

2.執(zhí)行該對(duì)象的同步塊

synchronize(obj) {
}

3.執(zhí)行某個(gè)類的靜態(tài)同步方法

public static synchronize b(){
}

Tips:擁有monitor的是線程竖共。

1.同時(shí)只能有一個(gè)線程可以獲取某個(gè)對(duì)象的monitor

2.一個(gè)線程通過調(diào)用某個(gè)對(duì)象的wait()方法釋放該對(duì)象的monitor并進(jìn)入休眠狀態(tài)蝙叛,直到其他線程獲取了被該線程釋放的monitor并調(diào)用該對(duì)象的notify()或者notifyAll()后再次競爭獲取該對(duì)象的monitor

3.只有擁有該對(duì)象monitor的線程才可以調(diào)用該對(duì)象的notify()和notifyAll()方法

如果沒有該對(duì)象monitor的線程調(diào)用了該對(duì)象的notify()或者notifyAll()方法將會(huì)拋出java.lang.IllegalMonitorStateException。

參考資料

https://blog.csdn.net/lkforce/article/details/81128115
https://blog.csdn.net/boyeleven/article/details/81390738
https://blog.csdn.net/hqq2023623/article/details/51000153


Kotlin開發(fā)者社區(qū)

專注分享 Java公给、 Kotlin借帘、Spring/Spring Boot、MySQL妓布、redis姻蚓、neo4j、NoSQL匣沼、Android、JavaScript捂龄、React释涛、Node、函數(shù)式編程倦沧、編程思想唇撬、"高可用,高性能展融,高實(shí)時(shí)"大型分布式系統(tǒng)架構(gòu)設(shè)計(jì)主題窖认。

High availability, high performance, high real-time large-scale distributed system architecture design

分布式框架:Zookeeper、分布式中間件框架等
分布式存儲(chǔ):GridFS扑浸、FastDFS烧给、TFS、MemCache喝噪、redis等
分布式數(shù)據(jù)庫:Cobar础嫡、tddl、Amoeba酝惧、Mycat
云計(jì)算榴鼎、大數(shù)據(jù)、AI算法
虛擬化晚唇、云原生技術(shù)
分布式計(jì)算框架:MapReduce巫财、Hadoop、Storm哩陕、Flink等
分布式通信機(jī)制:Dubbo平项、RPC調(diào)用、共享遠(yuǎn)程數(shù)據(jù)萌踱、消息隊(duì)列等
消息隊(duì)列MQ:Kafka葵礼、MetaQ,RocketMQ
怎樣打造高可用系統(tǒng):基于硬件并鸵、軟件中間件鸳粉、系統(tǒng)架構(gòu)等一些典型方案的實(shí)現(xiàn):HAProxy、基于Corosync+Pacemaker的高可用集群套件中間件系統(tǒng)
Mycat架構(gòu)分布式演進(jìn)
大數(shù)據(jù)Join背后的難題:數(shù)據(jù)园担、網(wǎng)絡(luò)届谈、內(nèi)存和計(jì)算能力的矛盾和調(diào)和
Java分布式系統(tǒng)中的高性能難題:AIO,NIO弯汰,Netty還是自己開發(fā)框架艰山?
高性能事件派發(fā)機(jī)制:線程池模型、Disruptor模型等等咏闪。曙搬。。

合抱之木鸽嫂,生于毫末纵装;九層之臺(tái),起于壘土据某;千里之行橡娄,始于足下。不積跬步癣籽,無以至千里挽唉;不積小流滤祖,無以成江河。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瓶籽,一起剝皮案震驚了整個(gè)濱河市匠童,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棘劣,老刑警劉巖俏让,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異茬暇,居然都是意外死亡首昔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門糙俗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勒奇,“玉大人,你說我怎么就攤上這事巧骚∩薜撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵劈彪,是天一觀的道長竣蹦。 經(jīng)常有香客問我,道長沧奴,這世上最難降的妖魔是什么痘括? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮滔吠,結(jié)果婚禮上纲菌,老公的妹妹穿的比我還像新娘。我一直安慰自己疮绷,他們只是感情好翰舌,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冬骚,像睡著了一般椅贱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上只冻,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天夜涕,我揣著相機(jī)與錄音,去河邊找鬼属愤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛酸役,可吹牛的內(nèi)容都是我干的住诸。 我是一名探鬼主播驾胆,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼贱呐!你這毒婦竟也來了丧诺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤奄薇,失蹤者是張志新(化名)和其女友劉穎驳阎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馁蒂,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡呵晚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沫屡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饵隙。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沮脖,靈堂內(nèi)的尸體忽然破棺而出金矛,到底是詐尸還是另有隱情,我是刑警寧澤勺届,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布驶俊,位于F島的核電站,受9級(jí)特大地震影響免姿,放射性物質(zhì)發(fā)生泄漏饼酿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一养泡、第九天 我趴在偏房一處隱蔽的房頂上張望嗜湃。 院中可真熱鬧,春花似錦澜掩、人聲如沸购披。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刚陡。三九已至,卻和暖如春株汉,著一層夾襖步出監(jiān)牢的瞬間筐乳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工乔妈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝙云,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓路召,卻偏偏與公主長得像勃刨,于是被迫代替她去往敵國和親波材。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355