iOS 多線程及線程安全

一碎浇、多線程的基本概念

進(jìn)程:可以理解成一個(gè)運(yùn)行中的應(yīng)用程序,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位璃俗。

線程:是進(jìn)程的基本執(zhí)行單元奴璃,一個(gè)進(jìn)程對(duì)應(yīng)多個(gè)線程。

主線程:處理UI城豁,所有更新UI的操作都必須在主線程上執(zhí)行苟穆。不要把耗時(shí)操作放在主線程,會(huì)卡界面。

多線程:在同一時(shí)刻雳旅,一個(gè)CPU只能處理1條線程跟磨,但CPU可以在多條線程之間快速的切換,只要切換的足夠快攒盈,就造成了多線程一同執(zhí)行的假象抵拘。

線程就像火車的一節(jié)車廂,進(jìn)程則是火車型豁。車廂(線程)離開火車(進(jìn)程)是無法跑動(dòng)的僵蛛,而火車(進(jìn)程)至少有一節(jié)車廂(主線程)。多線程可以看做多個(gè)車廂迎变,它的出現(xiàn)是為了提高效率充尉。

多線程是通過提高資源使用率來提高系統(tǒng)總體的效率。
我們運(yùn)用多線程的目的是:將耗時(shí)的操作放在后臺(tái)執(zhí)行衣形!

并發(fā)與并行:《并發(fā)的藝術(shù)》中大概是這樣寫的驼侠,系統(tǒng)中有多個(gè)任務(wù)同時(shí)存在可稱之為“并發(fā)”,系統(tǒng)內(nèi)有多個(gè)任務(wù)同時(shí)執(zhí)行可稱之為“并行”谆吴;并發(fā)是并行的子集倒源。比如在單核CPU系統(tǒng)上,只可能存在并發(fā)而不可能存在并行句狼。

二笋熬、線程的狀態(tài)與生命周期

下面分別闡述線程生命周期中的每一步

新建:實(shí)例化線程對(duì)象

就緒:向線程對(duì)象發(fā)送start消息,線程對(duì)象被加入可調(diào)度線程池等待CPU調(diào)度鲜锚。

運(yùn)行:CPU 負(fù)責(zé)調(diào)度可調(diào)度線程池中線程的執(zhí)行。線程執(zhí)行完成之前苫拍,狀態(tài)可能會(huì)在就緒和運(yùn)行之間來回切換芜繁。就緒和運(yùn)行之間的狀態(tài)變化由CPU負(fù)責(zé),程序員不能干預(yù)绒极。

阻塞:當(dāng)滿足某個(gè)預(yù)定條件時(shí)骏令,可以使用休眠或鎖,阻塞線程執(zhí)行垄提。sleepForTimeInterval(休眠指定時(shí)長)榔袋,sleepUntilDate(休眠到指定日期),@synchronized(self):(互斥鎖)铡俐。

死亡:正常死亡凰兑,線程執(zhí)行完畢。非正常死亡审丘,當(dāng)滿足某個(gè)條件后吏够,在線程內(nèi)部中止執(zhí)行/在主線程中止線程對(duì)象

還有線程的exit和cancel

[NSThread exit]:一旦強(qiáng)行終止線程,后續(xù)的所有代碼都不會(huì)被執(zhí)行。

[thread cancel]取消:并不會(huì)直接取消線程锅知,只是給線程對(duì)象添加 isCancelled 標(biāo)記播急。

三、多線程的四種解決方案

多線程的四種解決方案分別是:pthread(不常用)售睹,NSThread桩警,GCD, NSOperation昌妹。

1捶枢、NSThread

// 創(chuàng)建線程
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@""];
// 線程啟動(dòng),事情做完了才會(huì)死捺宗, 一個(gè)NSThread對(duì)象就代表一條線程
[thread start];
//判斷是否是主線程
[NSThread isMainThread]

優(yōu)點(diǎn):輕量級(jí)柱蟀,簡單易用,可以直接操作線程對(duì)象
缺點(diǎn): 需要自己管理線程的生命周期蚜厉、線程同步(NSLock加鎖進(jìn)行同步操作)长已。線程同步對(duì)數(shù)據(jù)的加鎖會(huì)有一定的系統(tǒng)開銷。

2昼牛、NSOperation

NSOperation是基于GCD的更高一層封裝术瓮,NSOperation需要配合NSOperationQueue來實(shí)現(xiàn)多線程。

兩種隊(duì)列

NSOperationQueue只有兩種隊(duì)列:主隊(duì)列贰健、其他隊(duì)列胞四。非主隊(duì)列(其他隊(duì)列)可以實(shí)現(xiàn)串行或并行。

主隊(duì)列的創(chuàng)建如下伶椿,主隊(duì)列上的任務(wù)是在主線程執(zhí)行的辜伟。

NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];

其他隊(duì)列(非主隊(duì)列)的創(chuàng)建如下,加入到‘非隊(duì)列’中的任務(wù)默認(rèn)就是并發(fā)脊另,開啟多線程导狡。

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

注意:

非主隊(duì)列(其他隊(duì)列)可以實(shí)現(xiàn)串行或并行。

隊(duì)列NSOperationQueue有一個(gè)參數(shù)叫做最大并發(fā)數(shù):maxConcurrentOperationCount偎痛。

maxConcurrentOperationCount默認(rèn)為-1旱捧,直接并發(fā)執(zhí)行,所以加入到‘非隊(duì)列’中的任務(wù)默認(rèn)就是并發(fā)踩麦,開啟多線程枚赡。

當(dāng)maxConcurrentOperationCount為1時(shí),則表示不開線程谓谦,也就是串行贫橙。

當(dāng)maxConcurrentOperationCount大于1時(shí),進(jìn)行并發(fā)執(zhí)行反粥。

系統(tǒng)對(duì)最大并發(fā)數(shù)有一個(gè)限制料皇,所以即使把maxConcurrentOperationCount設(shè)置的很大谓松,系統(tǒng)也會(huì)自動(dòng)調(diào)整。所以把最大并發(fā)數(shù)設(shè)置的很大是沒有意義的践剂。

子類

NSOperation是個(gè)抽象類鬼譬,實(shí)際運(yùn)用時(shí)中需要使用它的子類有三種方式:

使用子類NSInvocationOperation

使用子類NSBlockOperation

定義繼承自NSOperation的子類,通過實(shí)現(xiàn)內(nèi)部相應(yīng)的方法來封裝任務(wù)逊脯。

- (void)testOperationQueue {

    // 創(chuàng)建隊(duì)列优质,默認(rèn)并發(fā)

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    // 創(chuàng)建操作,NSInvocationOperation

    NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationOperationAddOperation) object:nil];

    // 創(chuàng)建操作军洼,NSBlockOperation

    NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

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

            NSLog(@"addOperation把任務(wù)添加到隊(duì)列======%@", [NSThread currentThread]);

        }

    }];

    [queue addOperation:invocationOperation];

    [queue addOperation:blockOperation];

}

- (void)invocationOperationAddOperation {

    NSLog(@"invocationOperation===aaddOperation把任務(wù)添加到隊(duì)列====%@", [NSThread currentThread]);

}

運(yùn)行結(jié)果如下巩螃,可以看出,任務(wù)都是在子線程執(zhí)行的匕争,開啟了新線程避乏!

依賴屬性

它有一個(gè)依賴屬性,某一個(gè)操作(operationB)依賴于另一個(gè)操作(operationA)甘桑,只有當(dāng)operationA執(zhí)行完畢拍皮,才能執(zhí)行operationB。

  [operationB addDependency:operationA];
取消/暫停/恢復(fù)操作
- (void)cancelAllOperations; 可以取消隊(duì)列的所有操作跑杭。
- (BOOL)isSuspended; 判斷隊(duì)列是否處于暫停狀態(tài)铆帽。 YES 為暫停狀態(tài),NO 為恢復(fù)狀態(tài)德谅。
- (void)setSuspended:(BOOL)b; 可設(shè)置操作的暫停和恢復(fù)爹橱,YES 代表暫停隊(duì)列,NO 代表恢復(fù)隊(duì)列窄做。
優(yōu)缺點(diǎn)

優(yōu)點(diǎn):不需要關(guān)心線程管理愧驱,數(shù)據(jù)同步的事情,可以把精力放在要執(zhí)行的操作上椭盏∽檠猓基于GCD,是對(duì)GCD 的封裝庸汗,比GCD更加面向?qū)ο蟊谷贰peration 之間添加依賴關(guān)系手报、取消一個(gè)正在執(zhí)行的 operation 蚯舱、暫停和恢復(fù) operation queue 等
缺點(diǎn): NSOperation是個(gè)抽象類,使用它必須使用它的子類

3掩蛤、GCD

GCD全稱Grand Central Dispatch枉昏,是非常常用的多線程解決方式,核心是dispatch隊(duì)列揍鸟,把需要處理的任務(wù)放到dispatch block中兄裂。GCD 管理著一個(gè)線程池句旱, 決定著dispatch block代碼塊將在哪個(gè)線程被執(zhí)行,并且對(duì)這些線程進(jìn)行管理晰奖,來緩解大量線程被創(chuàng)建的問題谈撒。

GCD的基本概念

同步(sync):任務(wù)一個(gè)接著一個(gè),前一個(gè)沒有執(zhí)行完匾南,后面不能執(zhí)行啃匿,不開線程。

異步(async):開啟多個(gè)新線程蛆楞,任務(wù)同一時(shí)間可以一起執(zhí)行溯乒。異步是多線程的代名詞

最大的區(qū)別在于,同步線程要阻塞當(dāng)前線程豹爹,必須要等待同步線程中的任務(wù)執(zhí)行完裆悄,返回以后,才能繼續(xù)執(zhí)行下一任務(wù)臂聋;而異步線程則是不用等待光稼。

阻塞一般是指:在調(diào)用結(jié)果返回之前,當(dāng)前線程會(huì)被掛起逻住。調(diào)用線程只有在得到結(jié)果之后才會(huì)被喚醒執(zhí)行后續(xù)的操作钟哥。

隊(duì)列:裝載線程任務(wù)的隊(duì)形結(jié)構(gòu)。(系統(tǒng)以先進(jìn)先出的方式調(diào)度隊(duì)列中的任務(wù)執(zhí)行)瞎访。在GCD中有兩種隊(duì)列:串行隊(duì)列和并發(fā)隊(duì)列腻贰。

并發(fā)隊(duì)列Concurrent Dispatch Queue:線程可以同時(shí)一起進(jìn)行執(zhí)行。實(shí)際上是CPU在多條線程之間快速的切換扒秸。(并發(fā)功能只有在異步(dispatch_async)函數(shù)下才有效)

串行隊(duì)列Serial Dispatch Queue:線程只能依次有序的執(zhí)行播演。

主隊(duì)列的任務(wù)一定在主線程中執(zhí)行

主線程可以執(zhí)行主隊(duì)列之外其他隊(duì)列的任務(wù).

串行與并行針對(duì)的是隊(duì)列,而同步與異步伴奥,針對(duì)的則是線程写烤。

GCD中的三種隊(duì)列類型

The main queue(主線程串行隊(duì)列): 與主線程功能相同,提交至Main queue的任務(wù)會(huì)在主線程中執(zhí)行拾徙,

Main queue 可以通過dispatch_get_main_queue()來獲取洲炊。

Global queue(全局并發(fā)隊(duì)列): 全局并發(fā)隊(duì)列由整個(gè)進(jìn)程共享,有高尼啡、中(默認(rèn))暂衡、低、后臺(tái)四個(gè)優(yōu)先級(jí)別崖瞭。

Global queue 可以通過調(diào)用dispatch_get_global_queue函數(shù)來獲瓤癯病(可以設(shè)置優(yōu)先級(jí))

    全局隊(duì)列的底層是一個(gè)線程池,向全局隊(duì)列中提交的 block书聚,都會(huì)被放到這個(gè)線程池中執(zhí)行唧领,如果線程池已滿藻雌,后續(xù)再提交 block 就不會(huì)再重新創(chuàng)建線程。等待前面的任務(wù)執(zhí)行完成斩个,才會(huì)繼續(xù)執(zhí)行胯杭。如果線程池中的線程長時(shí)間不結(jié)束,后續(xù)堆積的任務(wù)會(huì)越來越多受啥,此時(shí)就會(huì)存在 APP crash的風(fēng)險(xiǎn)歉摧。

Group queue (隊(duì)列組):將多線程進(jìn)行分組,最大的好處是可獲知所有線程的完成情況腔呜。

Group queue 可以通過調(diào)用dispatch_group_create()來獲取叁温,通過dispatch_group_notify,可以直接監(jiān)聽組里所有線程完成情況。

GCD的使用

1核畴、串行同步:當(dāng)前線程順序執(zhí)行膝但;

2、串行異步:分線程順序執(zhí)行谤草;

3跟束、并發(fā)同步:當(dāng)前線程順序執(zhí)行;

4丑孩、并發(fā)異步:分線程無序執(zhí)行冀宴;

5、主隊(duì)列同步: 死鎖温学,程序崩潰略贮;

(參考)http://ios.jobbole.com/82622/

6、主隊(duì)列異步:主線程順序執(zhí)行仗岖。

開發(fā)中關(guān)于gcd的運(yùn)用:

1逃延、開發(fā)中需要在主線程上進(jìn)行UI的相關(guān)操作,通常會(huì)把一些耗時(shí)的操作放在其他線程轧拄,比如說圖片文件下載等耗時(shí)操作揽祥。

2、GCD延時(shí)執(zhí)行

當(dāng)需要等待一會(huì)再執(zhí)行一段代碼時(shí)檩电,就可以用到這個(gè)方法了:dispatch_after拄丰。

3、GCD實(shí)現(xiàn)代碼只執(zhí)行一次

使用dispatch_once能保證某段代碼在程序運(yùn)行過程中只被執(zhí)行1次俐末×习矗可以用來設(shè)計(jì)單例。

4鹅搪、GCD隊(duì)列組

異步執(zhí)行幾個(gè)耗時(shí)操作站绪,當(dāng)這幾個(gè)操作都完成之后再回到主線程進(jìn)行操作遭铺,就可以用到隊(duì)列組了丽柿。隊(duì)列組有下面幾個(gè)特點(diǎn):

所有的任務(wù)會(huì)并發(fā)的執(zhí)行(不按序)恢准。

所有的異步函數(shù)都添加到隊(duì)列中,然后再納入隊(duì)列組的監(jiān)聽范圍甫题。

使用dispatch_group_notify函數(shù)馁筐,來監(jiān)聽上面的任務(wù)是否完成,如果完成, 就會(huì)調(diào)用這個(gè)方法坠非。

優(yōu)點(diǎn):輕量級(jí)的多線程解決方法敏沉,簡單易用,效率高炎码,速度快盟迟,基于C語言,更底層更高效潦闲,自動(dòng)管理線程生命周期(創(chuàng)建線程攒菠、調(diào)度任務(wù)、銷毀線程)歉闰。
缺點(diǎn): 1辖众、使用GCD的場景如果很復(fù)雜,就有非常大的可能遇到死鎖問題和敬。
2凹炸、如果想要給任務(wù)之間添加依賴關(guān)系、取消或者暫停一個(gè)正在執(zhí)行的任務(wù)時(shí)就會(huì)變得非常棘手

四昼弟、多線程安全

其實(shí)是多個(gè)線程同時(shí)訪問一個(gè)內(nèi)存區(qū)域出現(xiàn)的安全問題啤它。

解決多線程安全問題的方法 :

一:互斥鎖@synchronized(鎖對(duì)象)

防止不同的線程同時(shí)獲取相同的鎖 。當(dāng)新線程訪問時(shí)舱痘,如果發(fā)現(xiàn)其他線程正在執(zhí)行鎖定的代碼蚕键,新線程就會(huì)進(jìn)入休眠。

NSObject *obj = [[NSObject alloc] init];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        @synchronized(obj) {

            NSLog(@"需要線程同步的操作1 開始");

            sleep(3);

            NSLog(@"需要線程同步的操作1 結(jié)束");

        }

    });

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        sleep(1);

        @synchronized(obj) {

            NSLog(@"需要線程同步的操作2");

        }

    });

@synchronized(obj)指令使用的obj為該鎖的唯一標(biāo)識(shí)衰粹,只有當(dāng)標(biāo)識(shí)相同時(shí)锣光,才滿足互斥,如果線程2中的@synchronized(obj)改為@synchronized(self),線程2就不會(huì)被阻塞铝耻,@synchronized指令實(shí)現(xiàn)鎖的優(yōu)點(diǎn)就是我們不需要在代碼中顯式的創(chuàng)建鎖對(duì)象誊爹,便可以實(shí)現(xiàn)鎖的機(jī)制,但作為一種預(yù)防措施瓢捉,@synchronized塊會(huì)隱式的添加一個(gè)異常處理來保護(hù)代碼频丘,它會(huì)在異常拋出的時(shí)候自動(dòng)的釋放互斥鎖。

@synchronized(obj) block 會(huì)變成 objc_sync_enter 和 objc_sync_exit 的成對(duì)兒調(diào)用泡态。 調(diào)用 objc_sync_enter(obj) 時(shí)搂漠,它用 obj 內(nèi)存地址的哈希值查找合適的 SyncData,然后將其上鎖某弦。當(dāng)你調(diào)用 objc_sync_exit(obj) 時(shí)桐汤,它查找合適的 SyncData 并將其解鎖而克。

方法二:自旋鎖

加了自旋鎖,當(dāng)新線程訪問代碼時(shí)怔毛,如果發(fā)現(xiàn)有其他線程正在鎖定代碼员萍,新線程會(huì)用死循環(huán)的方式,一直等待鎖定的代碼執(zhí)行完成拣度。相當(dāng)于不停嘗試執(zhí)行代碼碎绎,比較消耗性能。

屬性修飾atomic本身就有一把自旋鎖抗果。

下面說一下屬性修飾nonatomic 和 atomic:
nonatomic 非原子屬性,同一時(shí)間可以有很多線程讀和寫
atomic 原子屬性(線程安全)筋帖,保證同一時(shí)間只有一個(gè)線程能夠?qū)懭?但是同一個(gè)時(shí)間多個(gè)線程都可以取值),atomic 本身就有一把鎖(自旋鎖)
atomic:線程安全冤馏,需要消耗大量的資源
nonatomic:非線程安全幕随,不過效率更高,一般使用nonatomic

五宿接、多線程的應(yīng)用及問題思考:

NSNotification是同步還是異步?:

1赘淮、在分線程發(fā)送一個(gè)通知

dispatch_async(dispatch_get_global_queue(0, 0), ^{

        [[NSNotificationCenter defaultCenter] postNotificationName:@"test" object:self userInfo:nil];

    });

主線程監(jiān)聽,并進(jìn)行UI操作

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNoti) name:@"test" object:nil];

- (void)receiveNoti {

    NSLog(@"isMainThread=%d", [NSThread isMainThread]);

    self.view.backgroundColor = [UIColor redColor];

}

結(jié)果:

isMainThread=0

=================================================================

Main Thread Checker: UI API called on a background thread: -[UIView setBackgroundColor:]

PID: 2318, TID: 88711, Thread name: (none), Queue name: com.apple.root.default-qos, QoS: 0

結(jié)論:

默認(rèn)情況下睦霎,創(chuàng)建的NSNotification是同步的梢卸,但是發(fā)布通知的時(shí)候在子線程中,那么接收方法觸發(fā)的也是在子線程中副女。

如何保證UI操作放在主線程中執(zhí)行蛤高?

SDWebImage的SDWebImageCompat.h中有這樣一個(gè)宏定義,用來保證主線程操作碑幅,為什么要這樣寫戴陡?

#ifndef dispatch_main_async_safe

#define dispatch_main_async_safe(block)\

    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(dispatch_get_main_queue())) == 0) {\

        block();\

    } else {\

        dispatch_async(dispatch_get_main_queue(), block);\

    }

#endif

在此之前見到最多的是這樣的:

#define dispatch_main_async_safe(block)\

    if ([NSThread isMainThread]) {\

        block();\

    } else {\

        dispatch_async(dispatch_get_main_queue(), block);\

    }

檢查我們當(dāng)前在主線程上執(zhí)行的最簡單的方法是使用[NSThread isMainThread] - GCD缺少一個(gè)類似的方便的API來檢查我們是否在主隊(duì)列上運(yùn)行,因此許多開發(fā)人員使用了NSThread API

這在大多數(shù)情況下是有效的沟涨,直到它出現(xiàn)了異常恤批。

image

潛在的問題是VektorKit API正在檢查是否在主隊(duì)列上調(diào)用它,而不是檢查它在主線程上運(yùn)行裹赴。

雖然每個(gè)應(yīng)用程序都只有一個(gè)主線程喜庞,但是在這個(gè)主線程上執(zhí)行許多不同的隊(duì)列是可能的。

如果庫(如VektorKit)依賴于在主隊(duì)列上檢查執(zhí)行棋返,那么從主線程上執(zhí)行的非主隊(duì)列調(diào)用API將導(dǎo)致問題延都。也就是說,如果在主線程執(zhí)行非主隊(duì)列調(diào)度的API睛竣,而這個(gè)API需要檢查是否由主隊(duì)列上調(diào)度晰房,那么將會(huì)出現(xiàn)問題。

來源參考

SDWebImage4.0源碼探究 http://www.reibang.com/p/b8517dc833c7

iOS多線程全套:線程生命周期,多線程的四種解決方案殊者,線程安全問題与境,GCD的使用,NSOperation的使用http://www.cocoachina.com/ios/20170707/19769.html

dispatch_barrier_(a)sync柵欄函數(shù)
https://blog.csdn.net/u013046795/article/details/47057585

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末幽污,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子簿姨,更是在濱河造成了極大的恐慌距误,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扁位,死亡現(xiàn)場離奇詭異准潭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)域仇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門刑然,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人暇务,你說我怎么就攤上這事泼掠。” “怎么了垦细?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵择镇,是天一觀的道長。 經(jīng)常有香客問我括改,道長腻豌,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任嘱能,我火速辦了婚禮吝梅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘惹骂。我一直安慰自己苏携,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布对粪。 她就那樣靜靜地躺著兜叨,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衩侥。 梳的紋絲不亂的頭發(fā)上国旷,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音茫死,去河邊找鬼跪但。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屡久。 我是一名探鬼主播忆首,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼被环!你這毒婦竟也來了糙及?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤筛欢,失蹤者是張志新(化名)和其女友劉穎浸锨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體版姑,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡柱搜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剥险。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片聪蘸。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖表制,靈堂內(nèi)的尸體忽然破棺而出健爬,到底是詐尸還是另有隱情,我是刑警寧澤么介,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布浑劳,位于F島的核電站,受9級(jí)特大地震影響夭拌,放射性物質(zhì)發(fā)生泄漏魔熏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一鸽扁、第九天 我趴在偏房一處隱蔽的房頂上張望蒜绽。 院中可真熱鬧,春花似錦桶现、人聲如沸躲雅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽相赁。三九已至,卻和暖如春慰于,著一層夾襖步出監(jiān)牢的瞬間钮科,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工婆赠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绵脯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蛆挫,于是被迫代替她去往敵國和親赃承。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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