java并發(fā)編程實(shí)戰(zhàn)讀書(shū)筆記:第三章 對(duì)象的共享

上一章講的是怎么通過(guò)同步來(lái)避免讓多個(gè)線程同時(shí)訪問(wèn)相同的數(shù)據(jù)儡首。
而這一章要講的是如何讓多個(gè)線程同時(shí)安全的訪問(wèn)一個(gè)對(duì)象毯焕。(如何安全的共享和發(fā)布對(duì)象)

我們?cè)谏弦徽轮懒丝梢允褂猛酱a塊或者同步方法來(lái)確保以原子的方式來(lái)執(zhí)行操作。
但有一個(gè)錯(cuò)誤的認(rèn)識(shí)是:認(rèn)為synchronized只能用于實(shí)現(xiàn)原子性或者確定臨界區(qū)在哪。(說(shuō)來(lái)慚愧,我一直也是這么以為的)
但它還有一個(gè)重要的功能:內(nèi)存可見(jiàn)性。我們有時(shí)候不僅希望一個(gè)對(duì)象的狀態(tài)只能被一個(gè)線程同時(shí)修改贫途。我們還希望當(dāng)一個(gè)線程修改了對(duì)象的狀態(tài)的時(shí)候,其他的線程可以看到狀態(tài)的變化待侵。這種就叫做對(duì)象被安全的發(fā)布丢早。

可見(jiàn)性

當(dāng)讀和寫(xiě)在不同的線程中執(zhí)行的時(shí)候,不能實(shí)時(shí)的看到其他線程寫(xiě)入的那個(gè)值秧倾,有時(shí)候是根本不可能的事怨酝。為了確保線程課件必須要使用同步機(jī)制。

public class Visbilityy {
    private boolean ready;
    private int number;
    
    private class ReaderThread extends Thread{
        /** (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            while (!ready) {
                Thread.yield();
            }
            System.out.println(number);
        }
    }
   
    public void test() {
        new ReaderThread().start();
        number = 42;
        ready = true;
    }
}

這種在大多數(shù)情況下都會(huì)正常輸出42那先。但是也有可能一直循環(huán)农猬,或者輸出0。這就是我們沒(méi)有在代碼中使用同步機(jī)制所導(dǎo)致的售淡。無(wú)法確保主線程寫(xiě)入的ready值和number值對(duì)讀線程是可見(jiàn)的斤葱。輸出0是因?yàn)榘l(fā)生“重排序”的情況:線程看到了ready的值但是沒(méi)有看到number的值。(ps:我自己的理解揖闸,就是jvm會(huì)對(duì)指令進(jìn)行重排序揍堕,導(dǎo)致真實(shí)的情況不是代碼里執(zhí)行的情況)

這個(gè)我在我電腦上試了同時(shí)6000次,也沒(méi)有出現(xiàn)過(guò)一直循環(huán)或者輸出是0的情況汤纸●萌祝可能這是跟電腦有關(guān)系的。有些時(shí)候值存在了不同的地方贮泞。這個(gè)得了解了jvm的實(shí)現(xiàn)機(jī)制才能知道到底是怎么回事楞慈。

有一種簡(jiǎn)單的做法能避免這些復(fù)雜的問(wèn)題:就是只要有數(shù)據(jù)字多個(gè)線程之間共享就應(yīng)該正確使用同步。

失效數(shù)據(jù)

上面的例子已經(jīng)展示了在缺少同步的程序中可能產(chǎn)生的一種情況:失效數(shù)據(jù)啃擦。當(dāng)讀線程查看ready變量時(shí)可能會(huì)得到一個(gè)失效的值囊蓝。
失效數(shù)據(jù)會(huì)導(dǎo)致一些令人困惑的問(wèn)題,比如數(shù)據(jù)結(jié)構(gòu)被破壞了令蛉,就按的不精確聚霜,無(wú)限循環(huán)等等。。俯萎。

@NotThreadSafe
public class MutableInteger {
      private int value;
      
      public int get () {return value;}

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

這種是線程不安全的。get和set不在同一線程的會(huì)有可能看不到互相运杭。

@ThreadSafe
public class SynchronizedInteger {
      @GuardeBy("this") private int value;

      public synchronized int get () {return value;}
      
      public synchronized void set ( int value){ this.value = value ;}
}
非原子的64位操作

這個(gè)很細(xì)節(jié)夫啊,不知道現(xiàn)在的jvm還是不是這樣- - ,基礎(chǔ)是多么重要辆憔。該好好看看關(guān)于jvm的書(shū)了

我們上面說(shuō)的失效數(shù)據(jù)撇眯,雖然是“失效的”。但是得到的這個(gè)值不是一個(gè)隨機(jī)的值虱咧,而是上一個(gè)有某個(gè)線程設(shè)置的值熊榛。這種稱(chēng)之為:最低安全性。

這里邊存在一個(gè)例外腕巡,就是非volatile類(lèi)型的64位數(shù)值變量:double玄坦,long。JVM允許將64位的讀操作或者寫(xiě)操作分解成兩個(gè)32位操作绘沉。當(dāng)讀取一個(gè)非volatile的long型煎楣,如果寫(xiě)操作在不同的線程中,那么很可能只會(huì)讀到一個(gè)值的高32位或者低32位车伞。即使不考慮失效性的問(wèn)題择懂,在多線程共享且可變的long和double類(lèi)型的變量也是線程不安全的。這時(shí)候應(yīng)該用volatile或者用鎖保護(hù)起來(lái)另玖。

加鎖和可見(jiàn)性

用內(nèi)置鎖可以確保一個(gè)線程可以預(yù)測(cè)另外一線程的執(zhí)行結(jié)果困曙。

我的理解:為什么用鎖了就可以保證內(nèi)存的可見(jiàn)性?可能執(zhí)行鎖里的代碼都是在一個(gè)特別的區(qū)域谦去,讀和寫(xiě)要是用的同一個(gè)鎖這樣會(huì)讓兩個(gè)線程對(duì)于同一個(gè)變量是可見(jiàn)的慷丽。

加鎖的含義不僅僅局限于互斥行為,還包括內(nèi)存可見(jiàn)性

書(shū)中的圖
Volatile 變量

Volatile變量時(shí)一種java提供的稍弱的同步機(jī)制鳄哭,這種機(jī)制用來(lái)確保將變量的更新操作通知到其他線程盈魁。
將變量聲明為volatile類(lèi)型后,在編譯器運(yùn)行的時(shí)候窃诉,會(huì)知道這個(gè)變量是要在線程之間共享的杨耙。所以不會(huì)將該變量的操作和其他內(nèi)存操作一起重排序。也不會(huì)被緩存在寄存器或者其他處理器不可見(jiàn)的地方(失效性)飘痛∩耗ぃ總之在讀取volatile類(lèi)型的變量總是會(huì)返回最新寫(xiě)人的值。

理解volatile變量一種有效的方法就是宣脉,將他們想象成SynchronizedInteger的類(lèi)似行為车柠,也就是說(shuō)volatile變量的讀操作和寫(xiě)操作分別替換為get方法和set方法。然而,在訪問(wèn)volatile變量時(shí)實(shí)際上不會(huì)有加鎖的操作竹祷,因此也就不會(huì)使線程阻塞了谈跛。
總的來(lái)說(shuō),volatile變量時(shí)一種比sychronized關(guān)鍵字更加輕量級(jí)的同步機(jī)制塑陵。

在使用volatile的時(shí)候要注意的點(diǎn):不要過(guò)度的使用volatile感憾。如果你要對(duì)變量進(jìn)行復(fù)雜地判斷就不要使用volatile變量。(就不是不要對(duì)volatile修飾變量進(jìn)行復(fù)雜的操作)正確的使用方法:確保自身狀態(tài)的可見(jiàn)性令花,確保他們所引用對(duì)象的狀態(tài)的可見(jiàn)性阻桅,以及標(biāo)識(shí)一些重要的程序聲明周期時(shí)間的發(fā)生(例如,初始化和關(guān)閉)兼都∩┏粒總之就是在一些不是那么復(fù)雜的變量的上面可以用volatile來(lái)修飾。要是很復(fù)雜扮碧,就還是用加鎖的方式來(lái)確保線程安全趟章。

注意:加鎖機(jī)制可以即確保可見(jiàn)性又可以確保原子性慎王,然而volatile變量只能確庇却В可見(jiàn)性。

當(dāng)且僅當(dāng)滿足以下條件才應(yīng)該使用volatile變量:

  • 對(duì)變量的寫(xiě)入操作不依賴(lài)變量的當(dāng)前值柬祠,或者保證只有一個(gè)線程會(huì)更新變量的值北戏。
  • 該變量不會(huì)與其他狀態(tài)變量一起納入不變性條件中。
  • 在訪問(wèn)變量時(shí)不需要加鎖
發(fā)布與逸出

“發(fā)布”是指對(duì)象能夠在其他地方使用和訪問(wèn)漫蛔。(就是可以隨意的獲得到這個(gè)對(duì)象的引用)嗜愈。當(dāng)不該發(fā)布的被發(fā)布了那么這種情況就是“逸出”。
如果發(fā)布某個(gè)對(duì)象的時(shí)候還是有可能會(huì)間接地發(fā)布其他對(duì)象莽龟。比如一個(gè)集合蠕嫁,可能會(huì)把集合里面的對(duì)象給暴露了出去。

安全的構(gòu)造對(duì)象
有時(shí)候我們會(huì)在構(gòu)造函數(shù)里不小心的引用了自己毯盈,就是不小心引用了this剃毒。
eg:

public class ThisEscape {
    public ThisEscape(EvenSource source){
          source.registerListener {
                 new EventListener() {
                        public void onEvent (Event e){
                              doSomething(e);
                        } 
                }           
          }
    }
}

在這個(gè)ThisEscape的構(gòu)造函數(shù)里,當(dāng)new EventLisener這個(gè)類(lèi)的的實(shí)例的時(shí)候就會(huì)順帶著把外部的ThisEscape這個(gè)實(shí)例也給發(fā)布了搂赋。這樣就會(huì)造成這個(gè)對(duì)象還沒(méi)有構(gòu)造完就應(yīng)經(jīng)被使用了赘阀。

針對(duì)于上面那種在構(gòu)造函數(shù)里注冊(cè)一個(gè)監(jiān)聽(tīng)事件的可以這么寫(xiě):

public class SafeListener {
    private final EventListener listener;

    private SafeListener () {
          listener = new EventListener() {
                  public void onEvent (Event e) {
                        doSomthing (e);
                  }
          }
    }

    public static SafeListener newInstance (EventSource source) {
            SafeLisenter safe = new SafeListener() ;
            source.registerListener (safe.listener);
            return safe;
    }
}

就是使用私有的構(gòu)造函數(shù)和一個(gè)公共的工廠方法來(lái)實(shí)現(xiàn)。(就是不要再?zèng)]構(gòu)造完就使用這個(gè)對(duì)象)

線程封閉

只在單線程里訪問(wèn)數(shù)據(jù)脑奠,這種被稱(chēng)為“線程封閉”基公。
例如我們?cè)谑褂玫膉dbc連接中的Connection對(duì)象。這個(gè)對(duì)象并不是線程安全的宋欺。但我們?cè)谑褂玫臅r(shí)候轰豆,基本都是在單線程中采用同步的方式來(lái)處理的胰伍。這種就隱含的將Connection封閉在線程中了。

  1. Ad-hoc 線程封閉
    保證線程封閉完全由程序來(lái)實(shí)現(xiàn)酸休。---非常脆弱
  2. 棧封閉
    就是使用局部變量骂租。(引用是在棧中)局部變量就是封閉在執(zhí)行線程中,他們?cè)诰€程的棧中斑司,其他線程無(wú)法訪問(wèn)到這個(gè)棧渗饮。(無(wú)法獲取到)

但也需要一些需要注意的地方。比如我們?cè)谏舷挛腸ontext里使用非線程安全的陡厘,雖然context是線程安全的抽米,但它里面的對(duì)象就不確定是否是線程安全的特占。

  1. ThreadLocal 類(lèi)
    這個(gè)類(lèi)會(huì)使得線程中的某個(gè)值和與保存值的對(duì)象關(guān)聯(lián)起來(lái)(我的理解:是讓線程和對(duì)象關(guān)聯(lián)起來(lái))糙置。ThreadLocal提供了get與set等訪問(wèn)接口的方法,這些方法為每個(gè)使用該變量的線程都存有一份獨(dú)立的副本是目,隱藏get總是返回當(dāng)前執(zhí)行線程在調(diào)用set時(shí)候的最新的值谤饭。
    ThreadLocal通常會(huì)用在對(duì)可變的單實(shí)例變量或者全局變量中使用的。當(dāng)多線程的應(yīng)用程序在沒(méi)有協(xié)同的情況下使用全局變量的時(shí)候懊纳,這時(shí)候?qū)⑦@個(gè)變量放在ThreadLocal中揉抵,這樣就會(huì)讓每個(gè)線程使用的不影響。
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal <Connection>() {
      public Connection initalValue () {
              return DreiverManager.getConnection (DB_URL);
      }
};
public static Connection getConnection(0 {
       return connectionHolder.get();
}

使用這種方法的缺點(diǎn)就是使得代碼的耦合性更高了

不變性

如果共享的變量時(shí)不可變的嗤疯,那么上面說(shuō)的失效數(shù)據(jù)冤今、丟失更新操作或者競(jìng)態(tài)條件這些問(wèn)題都不會(huì)出現(xiàn)了。

不可變的對(duì)象一定是線程安全的

那什么是不可變的對(duì)象呢茂缚?

  • 對(duì)象穿件以后狀態(tài)不能被改變
  • 對(duì)象所有的域都是final類(lèi)型的
  • 對(duì)象是正確創(chuàng)建的(創(chuàng)建期間戏罢,this引用沒(méi)有逸出)

需要注意的是不可變不等于將對(duì)象所有的域都聲明為final類(lèi)型,即使所有的域都是final類(lèi)型脚囊,但這個(gè)對(duì)象也有可能是可變的龟糕,因?yàn)樵趂inal類(lèi)型的域中可以把村對(duì)可變對(duì)象的引用。

  1. Final域
    final 可以保證初始化過(guò)程的安全性悔耘。

除非需要更高的可見(jiàn)性讲岁,否則應(yīng)將所有的域都聲明為私有域是一個(gè)良好的編程習(xí)慣,除非需要某個(gè)域是可變的衬以,否則應(yīng)將其聲明為final域缓艳。

  1. 使用Volatile類(lèi)型來(lái)發(fā)布不可變對(duì)象
    保存在不可變對(duì)象中的程序狀態(tài)仍然是可以更新的,即通過(guò)一個(gè)保存新?tīng)顟B(tài)的示例來(lái)“替換”原有的不可變對(duì)象看峻。
    示例:
    因式分解Servlet將執(zhí)行兩個(gè)原子操作:更新緩存的結(jié)果郎任,判斷緩存中數(shù)值是否等于請(qǐng)求的數(shù)值來(lái)決定是否取緩存中的結(jié)果。這時(shí)候就可以考慮創(chuàng)建一個(gè)不可變的類(lèi)來(lái)包含這些數(shù)據(jù)备籽。
@Immutable
public class OneValueCache {
    private final BigInteger lastNumber;
    private final BigInteger[] lastFactors;
    
    public OneValueCache(BigInteger i,BigInteger[] factors) {
        lastNumber = i;
        lastFactors = Arrays.copyOf(factors, factors.length);
    }
    //判斷是否是以前緩存上的
    public BigInteger[] getFactors(BigInteger i) {
        if(lastNumber == null || !lastNumber.equals(i))
            return null;
        else
            return Arrays.copyOf(lastFactors, lastFactors.length);
    }
}
public class VolatileCachedFactorizer implements Servlet {

    private volatile OneValueCache cache = new OneValueCache (null,null);
    
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        BigInteger i = extractFormRequest (arg0);
        //調(diào)用不可變對(duì)象的方法來(lái)判斷是否相同舶治,即使準(zhǔn)備個(gè)cache被別的線程修改也無(wú)所謂分井,這里返回的始終是這個(gè)i的因子
        BigInteger[] factors = cache.getFactors(i);
        if (factors == null) {
            factors = factor(i);
            cache = new OneValueCache(i, factors);
        }
        encodeIntoResponse (arg1,factors);
    }
}

上面的例子是用volatile類(lèi)型來(lái)保證課件行,每次都創(chuàng)建新的不可變對(duì)象來(lái)確保不變性霉猛。

安全發(fā)布

對(duì)象怎么能安全的進(jìn)行共享呢尺锚?(其實(shí)上面已經(jīng)把需要注意的點(diǎn)都說(shuō)了,這里就是總結(jié)下惜浅,說(shuō)下方法)

  • 安全發(fā)布的常用模式

在靜態(tài)初始化函數(shù)中初始化一個(gè)對(duì)象引用
將對(duì)象的引用保存到volatile類(lèi)型的域中
將對(duì)象的引用保存到某個(gè)正確構(gòu)造對(duì)象的final類(lèi)型中
將對(duì)象的引用保存到一個(gè)由鎖保護(hù)的域中

我的理解:

  1. 一般都寫(xiě)一個(gè)靜態(tài)變量 eg: public static Holder holder = new Holder(42);
  2. 然后為了讓多個(gè)線程可見(jiàn)使用volatile
  3. 然后保證這個(gè)引用不會(huì)去指向其他的對(duì)象瘫辩,使用final
  4. 然后把這個(gè)對(duì)象放在一個(gè)鎖里進(jìn)行訪問(wèn)(自己寫(xiě)的也可以,也可以使用Hashtable,synchronizedMap,Vector這些線程安全的容器里)
  • 事實(shí)不可變對(duì)象
    上面說(shuō)的是怎么安全發(fā)布可變的對(duì)象坛悉,還存在一種可變對(duì)象伐厌,叫“事實(shí)不可變對(duì)象”:再發(fā)布后不會(huì)被修改。雖然是可變的但是我們保證這個(gè)沒(méi)有對(duì)這個(gè)對(duì)象寫(xiě)的方法裸影。

在沒(méi)有額外的同步的情況下挣轨,任何線程都可以安全的使用被安全發(fā)布的事實(shí)不可變對(duì)象。

eg:Date本身就是可變的轩猩,但是它就可以作為不可變對(duì)象來(lái)使用卷扮,咋多個(gè)線程之間共享Date對(duì)象時(shí)就可以省去對(duì)鎖的使用。

public Map<String, Date> lastLogin = Collections.synchronizedMap(new HashMap<String, Date>);

synchronizedMap中的同步機(jī)制就足以保證Date被安全地發(fā)布均践,不需要在訪問(wèn)Date時(shí)做額外的同步

  • 可變對(duì)象
    如果對(duì)象在構(gòu)造后可以修改晤锹,那么安全發(fā)布只能確保“發(fā)布當(dāng)時(shí)”狀態(tài)的可見(jiàn)性彤委。對(duì)于可變對(duì)象鞭铆,不僅要在發(fā)布對(duì)象時(shí)候需要使用同步,還要在每次的對(duì)象訪問(wèn)時(shí)候使用同步來(lái)確保安全焦影。

不可變對(duì)象可以通過(guò)任意機(jī)制來(lái)發(fā)布
事實(shí)不可變對(duì)象必須通過(guò)安全方式來(lái)發(fā)布
并且必須是線程安全的或者是由某一個(gè)鎖保護(hù)起來(lái)

  • 安全地共享對(duì)象
    在我們獲得一個(gè)對(duì)象的引用的時(shí)候车遂,你需要知道和了解我們的會(huì)在這個(gè)引用上執(zhí)行哪些操作。是否需要獲得一個(gè)鎖偷办?是否可以修改它狀態(tài)艰额,或者只能讀取它?許多并發(fā)錯(cuò)誤都是由于沒(méi)有理解共享對(duì)象的這些規(guī)則鎖導(dǎo)致的椒涯。

在并發(fā)程序中使用和共享對(duì)象時(shí)柄沮, 一些使用策略:
線程封閉:線程封閉的對(duì)象只能由一個(gè)線程所擁有
只讀共享:只能被多個(gè)線程并發(fā)訪問(wèn),不能修改它
線程安全共享:線程安全的對(duì)象在起內(nèi)部實(shí)現(xiàn)同步废岂,因此多個(gè)線程統(tǒng)一通過(guò)對(duì)象的公用方法來(lái)訪問(wèn)祖搓,不需要進(jìn)一步同步。
保護(hù)對(duì)象:使用特定的鎖來(lái)訪問(wèn)湖苞。保護(hù)對(duì)象包括封裝在其他線程安全中的對(duì)象拯欧,已經(jīng)已發(fā)布的并且有某個(gè)特定鎖保護(hù)的對(duì)象。

上面說(shuō)的是我們?cè)诰帉?xiě)一個(gè)多線程程序的時(shí)候所需要考慮的步驟财骨。

  1. 先考慮是否可以不共享對(duì)象
  2. 必須要共享對(duì)象的時(shí)候镐作,是否這個(gè)對(duì)象是只需要訪問(wèn)的藏姐,不需要在多個(gè)線程里進(jìn)行寫(xiě)操作
  3. 如果這個(gè)共享的對(duì)象既需要讀又需要寫(xiě),那么我們可以考慮為這個(gè)對(duì)象封裝些同步訪問(wèn)和修改的方法
  4. 如果不只是一個(gè)對(duì)象该贾,需要很多共享對(duì)象互相操作比較復(fù)雜羔杨,這時(shí)候應(yīng)該就使用特定的鎖來(lái)進(jìn)行訪問(wèn)這些對(duì)象

上面是我自己的理解,不知道我理解的對(duì)不對(duì)哈杨蛋。兜材。。如有不對(duì)請(qǐng)大家指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末逞力,一起剝皮案震驚了整個(gè)濱河市曙寡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌寇荧,老刑警劉巖举庶,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異砚亭,居然都是意外死亡灯变,警方通過(guò)查閱死者的電腦和手機(jī)殴玛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)捅膘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人滚粟,你說(shuō)我怎么就攤上這事寻仗。” “怎么了凡壤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵署尤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我亚侠,道長(zhǎng)曹体,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任硝烂,我火速辦了婚禮箕别,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘滞谢。我一直安慰自己串稀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布狮杨。 她就那樣靜靜地躺著母截,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橄教。 梳的紋絲不亂的頭發(fā)上清寇,一...
    開(kāi)封第一講書(shū)人閱讀 52,682評(píng)論 1 312
  • 那天史辙,我揣著相機(jī)與錄音堪滨,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遭垛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播姑躲,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棠涮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了比吭?” 一聲冷哼從身側(cè)響起绽族,我...
    開(kāi)封第一講書(shū)人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衩藤,沒(méi)想到半個(gè)月后吧慢,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赏表,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年检诗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓢剿。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逢慌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出间狂,到底是詐尸還是另有隱情攻泼,我是刑警寧澤,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布鉴象,位于F島的核電站忙菠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纺弊。R本人自食惡果不足惜牛欢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淆游。 院中可真熱鬧傍睹,春花似錦、人聲如沸稽犁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)已亥。三九已至熊赖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間虑椎,已是汗流浹背震鹉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工俱笛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人传趾。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓迎膜,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親浆兰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磕仅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

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