多線程使用要注意哪些事項(xiàng)

使用多線程是每個(gè)程序員必須要掌握的读串。然而使用多線程的時(shí)候,如果不加注意就會(huì)產(chǎn)生很多比較難排查的bug。所以要對(duì)多線程有深入的理解才行念赶。比如可變數(shù)組和可變字典是線程安全的嗎?本身就是異步執(zhí)行的任務(wù)恰力,如何等待真正的結(jié)果返回之后才繼續(xù)后面的事情叉谜?在線程中睡眠,睡醒之后當(dāng)前類已經(jīng)釋放踩萎,self會(huì)為nil嗎?等等停局,在多線程的實(shí)際使用過(guò)程中會(huì)有很多出現(xiàn),因此需要把基礎(chǔ)打牢香府,也要有更深的理解董栽。

首先從最基本的定義說(shuō)起

什么是進(jìn)程?

進(jìn)程是線程的容器企孩。程序是指令裆泳、數(shù)據(jù)及其組織形式的描述,進(jìn)程是程序的實(shí)體柠硕。

狹義定義:進(jìn)程是正在運(yùn)行的程序的實(shí)例(an instance of a computer program that is being executed)工禾。

上面是百科的部分定義,簡(jiǎn)單來(lái)說(shuō)蝗柔,每個(gè)應(yīng)用啟動(dòng)之后闻葵,都對(duì)應(yīng)著一個(gè)進(jìn)程。打開(kāi)活動(dòng)監(jiān)視器即可看到癣丧,第一列就是進(jìn)程名稱槽畔,每一個(gè)程序?qū)?yīng)一個(gè)進(jìn)程,每個(gè)進(jìn)程都有一個(gè)唯一標(biāo)示PID胁编,即進(jìn)程ID厢钧。

進(jìn)程概念主要有兩點(diǎn):

  1. 進(jìn)程是一個(gè)實(shí)體。每個(gè)進(jìn)程都有自己的地址空間嬉橙,一般情況下包括 文本區(qū)域text region早直、數(shù)據(jù)區(qū)域data region 和堆棧stack region。
  2. 進(jìn)程是一個(gè)執(zhí)行中的程序市框。程序是一個(gè)沒(méi)有生命的實(shí)體霞扬,只有程序執(zhí)行的時(shí)候,它才能成為一個(gè)活動(dòng)的實(shí)體。我們稱它為進(jìn)程喻圃。

除去進(jìn)程的新建和終止萤彩,運(yùn)行中的進(jìn)程具有三種基本狀態(tài):

運(yùn)行中的進(jìn)程狀態(tài)
  • 就緒:進(jìn)程已經(jīng)獲得除處理器外的所需資源,等待分配處理器資源斧拍。只要分配了處理器進(jìn)程就可以執(zhí)行雀扶。
  • 運(yùn)行:進(jìn)行占用處理器資源,出于此狀態(tài)的運(yùn)行數(shù)小于等于處理器數(shù)
  • 阻塞:由于進(jìn)程等待某種條件肆汹,比如I/O操作或者進(jìn)程同步愚墓,在條件滿足之前無(wú)法繼續(xù)執(zhí)行

什么是線程?

線程是程序執(zhí)行的最小單元县踢。一個(gè)標(biāo)準(zhǔn)的線程由線程ID转绷,當(dāng)前指令指針,寄存器集合和堆棧組成硼啤。線程是進(jìn)程中的一個(gè)實(shí)體议经。線程也具有就緒,阻塞和運(yùn)行三種基本狀態(tài)谴返。

通常一個(gè)進(jìn)行中可以包含若干個(gè)線程煞肾,它們可以利用進(jìn)程所擁有的全部資源。進(jìn)程是分配資源的基本單位嗓袱。而線程則是獨(dú)立運(yùn)行和調(diào)度的基本單位籍救。由于線程比進(jìn)程更小,基本上不擁有系統(tǒng)資源渠抹,只擁有一點(diǎn)兒在運(yùn)行中必不可少的資源蝙昙,但它可與同屬一個(gè)進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。

線程是進(jìn)程的基本執(zhí)行單元梧却,進(jìn)程的所有任務(wù)都是在線程中執(zhí)行的奇颠。

多線程的實(shí)現(xiàn)原理

先說(shuō)下任務(wù)執(zhí)行有兩種方式,串行和并行放航。

串行:任務(wù)一個(gè)一個(gè)執(zhí)行烈拒,所需時(shí)間是所有任務(wù)執(zhí)行完成之和。

并行:任務(wù)并發(fā)執(zhí)行广鳍,所需時(shí)間是耗時(shí)最久的任務(wù)完成時(shí)間荆几。

任務(wù)的串行于行與線程并沒(méi)有必然的聯(lián)系。串行并非就只有一個(gè)線程赊时,也可以有多個(gè)線程吨铸。并行必然有多個(gè)線程。

對(duì)于單核操作系統(tǒng)蛋叼,同一時(shí)間只有一個(gè)線程在執(zhí)行焊傅。每個(gè)線程都分配有時(shí)間片進(jìn)行執(zhí)行剂陡,然后切換到其他線程狈涮。從宏觀來(lái)看是并行的狐胎,從微觀上來(lái)看,是串行的歌馍。

對(duì)于多核操作系統(tǒng)握巢,就真正實(shí)現(xiàn)了并行執(zhí)行任務(wù)。在同一時(shí)間可以有多個(gè)線程在執(zhí)行任務(wù)松却。

多線程的場(chǎng)景使用場(chǎng)景:

在iOS系統(tǒng)中,UIKit中的所有操作都是在主線程中執(zhí)行的晓锻,包括用戶的觸摸事件等歌焦。如果在主線程執(zhí)行耗時(shí)操作就會(huì)造成卡頓等現(xiàn)象,影響用戶體驗(yàn)砚哆。常見(jiàn)的耗時(shí)操作有:

  • 網(wǎng)絡(luò)請(qǐng)求

  • 圖片加載

  • 文件處理

  • 數(shù)據(jù)存儲(chǔ)

  • 多任務(wù)

常見(jiàn)實(shí)現(xiàn)方式

  • pThread --c 語(yǔ)言
  • NSThread -- oc對(duì)象
  • GCD -- c語(yǔ)言
  • NSOpreation -- oc對(duì)象

pThread 用的是一套c語(yǔ)言庫(kù)独撇,在iOS開(kāi)發(fā)中使用的不多。

使用時(shí)需要先導(dǎo)入頭文件#import <pthread.h>

使用時(shí)創(chuàng)建線程躁锁,并指定執(zhí)行的方法即可

- (IBAction)pThreadClicked:(UIButton *)sender {
    NSLog(@"主線程事件");
    pthread_t pthread;
    pthread_create(&pthread, NULL, run, NULL);
}

void *run(){
    NSLog(@"run方法執(zhí)行");
    sleep(1);
    NSLog(@"執(zhí)行結(jié)束");
    return NULL;
}
// 打印結(jié)果4540是進(jìn)程id纷铣,后面的是線程id,打印結(jié)果可以看出run在子線程中執(zhí)行战转。
2019-01-03 17:22:26.260893+0800 ThreadTest[4540:1088694] 主線程事件
2019-01-03 17:22:26.262011+0800 ThreadTest[4540:1089164] run方法執(zhí)行
2019-01-03 17:22:27.263254+0800 ThreadTest[4540:1089164] 執(zhí)行結(jié)束
    

因?yàn)閜hread不常用搜立,所以也不做多做介紹,使用的時(shí)候時(shí)候看一下官方的api就可以了槐秧。

NSThread 的三種創(chuàng)建方式

? // 1. 對(duì)象方式啄踊,可以獲取到線程對(duì)象,需要手動(dòng)執(zhí)行start方法,當(dāng)然也方便設(shè)置其他屬性刁标,比如優(yōu)先級(jí)颠通,比如線程名字等。

- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
- (IBAction)NSTreadClick:(UIButton *)sender {
    NSLog(@"主線程");
    NSThread *thread = [[NSThread alloc]initWithBlock:^{
        sleep(1);
        NSLog(@"子線程");
    }];
    thread.name = @"thread1";
    thread.threadPriority = 1.0;
    [thread start];
}
// 打印結(jié)果
2019-01-03 17:44:14.421668+0800 ThreadTest[4668:1122856] 主線程
2019-01-03 17:44:15.423002+0800 ThreadTest[4668:1123018] 子線程

? // 2. 類方法 不能直接獲取線程對(duì)象 不過(guò)可以在線程執(zhí)行過(guò)程中使用類方法currentThread獲取當(dāng)前線程

+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;

// 3. NSObject的分類方法命雀,不能直接獲取線程對(duì)象

- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));

GCD

以下面的代碼為例

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
       ... 
    });
// async 異步
// get_global_queue 并發(fā)
// ^{       ...     } 執(zhí)行的任務(wù)

GCD的使用需要告訴gcd三個(gè)東西

  1. 同步 還是 異步:同步會(huì)阻塞當(dāng)前線程蒜哀,異步不會(huì)阻塞。
  2. 在哪個(gè)隊(duì)列:隊(duì)列分為串行和并行吏砂,即需要一個(gè)一個(gè)執(zhí)行還是需要并發(fā)執(zhí)行撵儿。
  3. 任務(wù)是什么: block中的東西即是要執(zhí)行的任務(wù)。

主隊(duì)列:dispatch_get_main_queue() 串行隊(duì)列

全局隊(duì)列: dispatch_get_global_queue(<#long identifier#>, <#unsigned long flags#>) 并發(fā)隊(duì)列

舉個(gè)異步執(zhí)行任務(wù)回到主線程刷新的例子:

- (IBAction)gcdClick:(UIButton *)sender {
    NSLog(@"用戶點(diǎn)擊事件在主線程");
    // 在自線程執(zhí)行任務(wù)
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"start...");
        [NSThread sleepForTimeInterval:3];
        NSLog(@"end...");
        // 回到主線程 刷新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"回到主線程刷新UI");
        });
    });
}
// 打印 可以通過(guò)線程id區(qū)分是不是主線程狐血,也可以打印當(dāng)前線程
2019-01-03 19:14:14.841561+0800 ThreadTest[4789:1195593] 用戶點(diǎn)擊事件在主線程
2019-01-03 19:14:14.841752+0800 ThreadTest[4789:1195941] start...
2019-01-03 19:14:17.845246+0800 ThreadTest[4789:1195941] end...
2019-01-03 19:14:17.845676+0800 ThreadTest[4789:1195593] 回到主線程刷新UI

獲取全局隊(duì)列時(shí)淀歇,第一個(gè)參數(shù)是設(shè)置優(yōu)先級(jí)的,第二個(gè)是預(yù)留參數(shù)匈织,暫時(shí)沒(méi)有用浪默。優(yōu)先級(jí)越高牡直,先執(zhí)行的概率越大。

進(jìn)行串行執(zhí)行纳决,串行還是并發(fā)和同步異步?jīng)]有關(guān)系碰逸,也就是和線程沒(méi)有必然的聯(lián)系,我們舉個(gè)例子來(lái)說(shuō)明這一點(diǎn)阔加,同步因?yàn)闆](méi)有開(kāi)啟線程必然是串行的饵史,但異步如果指定了串行隊(duì)列,也會(huì)一個(gè)一個(gè)執(zhí)行胜榔。

同步的串行:

    // 同步 -- 串行
    NSLog(@"當(dāng)前主線程");
    dispatch_queue_t serial = dispatch_queue_create("com.test.gcd", DISPATCH_QUEUE_SERIAL);
    dispatch_sync(serial, ^{
        NSLog(@"sync-task1");
    });
    dispatch_sync(serial, ^{
        NSLog(@"sync-task2");
    });
    dispatch_sync(serial, ^{
        NSLog(@"sync-task3");
    });

異步的串行:

    //異步 -- 串行
    dispatch_async(serial, ^{
        NSLog(@"async-task1");
    });
    dispatch_async(serial, ^{
        NSLog(@"async-task2");
    });
    dispatch_async(serial, ^{
        NSLog(@"async-task3");
    });

上述兩者的打印結(jié)果如下:

2019-01-03 19:28:09.275753+0800 ThreadTest[4836:1220108] 當(dāng)前主線程
2019-01-03 19:28:09.276001+0800 ThreadTest[4836:1220108] sync-task1
2019-01-03 19:28:09.276151+0800 ThreadTest[4836:1220108] sync-task2
2019-01-03 19:28:09.276287+0800 ThreadTest[4836:1220108] sync-task3
2019-01-03 19:28:09.276452+0800 ThreadTest[4836:1220151] async-task1
2019-01-03 19:28:09.276656+0800 ThreadTest[4836:1220151] async-task2
2019-01-03 19:28:09.277657+0800 ThreadTest[4836:1220151] async-task3

上述結(jié)果說(shuō)明:

  1. 同步時(shí)胳喷,沒(méi)有開(kāi)啟線程。
  2. 異步時(shí)夭织,開(kāi)啟了線程吭露,因?yàn)槭谴校灾婚_(kāi)了一個(gè)線程尊惰。
  3. 串行是為了保證任務(wù)的順序執(zhí)行讲竿,并行是為了保證任務(wù)的并發(fā)執(zhí)行,串行沒(méi)有創(chuàng)建新線程择浊,并行會(huì)根據(jù)需要至少創(chuàng)建一個(gè)線程戴卜。

關(guān)于同步&異步。串行&并行 可以列個(gè)象限圖

有四種組合:

  • 同步-串行:同步會(huì)阻塞當(dāng)前線程琢岩,因此不會(huì)創(chuàng)建線程投剥,也可以保證任務(wù)同步執(zhí)行

  • 同步-并發(fā):同步會(huì)阻塞當(dāng)前線程,所以不會(huì)創(chuàng)建線程担孔,所以無(wú)法實(shí)現(xiàn)并發(fā)江锨,實(shí)際上還是串行。

  • 異步-串行:異步不會(huì)阻塞當(dāng)前線程糕篇,會(huì)創(chuàng)建新線程啄育,為保證串行,一般創(chuàng)建一個(gè)線程就夠了拌消。

  • 異步-并發(fā):異步不會(huì)阻塞當(dāng)前線程挑豌,會(huì)創(chuàng)建新線程,為保證并發(fā)墩崩,一般會(huì)創(chuàng)建多個(gè)線程氓英。

這里重點(diǎn)說(shuō)明一下同步-并發(fā) 其實(shí)因?yàn)橥綍?huì)阻塞線程所以不能并發(fā)

    // 同步-并發(fā),實(shí)際無(wú)法實(shí)現(xiàn)并發(fā)鹦筹,依然是串行執(zhí)行
    NSLog(@"當(dāng)前主線程");
    dispatch_queue_t async = dispatch_queue_create("com.test.async", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 8; i++) {
        dispatch_sync(async, ^{
            NSLog(@"sync_concurrent_task%d",i);
        });
    }
// 打印結(jié)果 并沒(méi)有創(chuàng)建新的線程铝阐,所以并不是并發(fā)執(zhí)行的。
2019-01-03 19:44:25.405840+0800 ThreadTest[4888:1241863] 當(dāng)前主線程
2019-01-03 19:44:25.406140+0800 ThreadTest[4888:1241863] sync_concurrent_task0
2019-01-03 19:44:25.406288+0800 ThreadTest[4888:1241863] sync_concurrent_task1
2019-01-03 19:44:25.406429+0800 ThreadTest[4888:1241863] sync_concurrent_task2
2019-01-03 19:44:25.406534+0800 ThreadTest[4888:1241863] sync_concurrent_task3
2019-01-03 19:44:25.406634+0800 ThreadTest[4888:1241863] sync_concurrent_task4
2019-01-03 19:44:25.406756+0800 ThreadTest[4888:1241863] sync_concurrent_task5
2019-01-03 19:44:25.407134+0800 ThreadTest[4888:1241863] sync_concurrent_task6
2019-01-03 19:44:25.407561+0800 ThreadTest[4888:1241863] sync_concurrent_task7

// 任務(wù)組 — 用來(lái)一組任務(wù)結(jié)束之后铐拐,再執(zhí)行其他操作徘键,組任務(wù)結(jié)束之后會(huì)調(diào)用notify方法

    NSLog(@"當(dāng)前主線程");
dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t group_queue = dispatch_queue_create("com.test.group", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_async(group, group_queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group task 1");
    });
    dispatch_group_async(group, group_queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group task 2");
    });
    dispatch_group_async(group, group_queue, ^{
        [NSThread sleepForTimeInterval:2];
        NSLog(@"group task 3");
    });
    
    dispatch_group_notify(group, group_queue, ^{
        NSLog(@"all task done");
    });
// 打印 啟用了三個(gè)線程 任務(wù)等待完成之后執(zhí)行练对。
2019-01-03 19:55:20.669903+0800 ThreadTest[4924:1260901] 當(dāng)前主線程
2019-01-03 19:55:22.674533+0800 ThreadTest[4924:1260946] group task 2
2019-01-03 19:55:22.674533+0800 ThreadTest[4924:1260947] group task 1
2019-01-03 19:55:22.674533+0800 ThreadTest[4924:1260945] group task 3
2019-01-03 19:55:22.674753+0800 ThreadTest[4924:1260946] all task done

需要注意的是:以上每一個(gè)任務(wù)本身就是同步的,如果任務(wù)本身就是異步的吹害,每個(gè)任務(wù)很快就會(huì)執(zhí)行螟凭,可能獲取不到我們想要的結(jié)果。比如我們模擬一個(gè)異步請(qǐng)求赠制。

    // 任務(wù)組
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t group_queue = dispatch_queue_create("com.test.group", DISPATCH_QUEUE_CONCURRENT);

    dispatch_group_async(group, group_queue, ^{
        [self requestOneInfo:^{
            NSLog(@"one info done");
        }];
    });
    
    dispatch_group_async(group, group_queue, ^{
        [self requestOtherInfo:^{
            NSLog(@"other info done");
        }];
    });
    
    dispatch_group_notify(group, group_queue, ^{
        NSLog(@"all task done");
    });
// 打印結(jié)果 很明顯不是我們想要的
2019-01-03 20:07:51.231103+0800 ThreadTest[4950:1281306] 當(dāng)前主線程
2019-01-03 20:07:51.231406+0800 ThreadTest[4950:1281362] get OneInfo start
2019-01-03 20:07:51.231426+0800 ThreadTest[4950:1281360] all task done
2019-01-03 20:07:51.231414+0800 ThreadTest[4950:1281359] get OtherInfo start
2019-01-03 20:07:53.234123+0800 ThreadTest[4950:1281359] get OtherInfo end
2019-01-03 20:07:53.234130+0800 ThreadTest[4950:1281362] get OneInfo end
2019-01-03 20:07:53.234489+0800 ThreadTest[4950:1281359] other info done
2019-01-03 20:07:53.234491+0800 ThreadTest[4950:1281362] one info done

以上結(jié)果很明顯不是我們想要的赂摆,就是因?yàn)槿蝿?wù)本身是異步執(zhí)行的挟憔,任務(wù)組的任務(wù)很快就結(jié)束了钟些,真正的任務(wù)并沒(méi)有結(jié)束。這個(gè)時(shí)候绊谭,我們需要使用 enter 和 leave , enter 和 leave要成對(duì)出現(xiàn)政恍。

我們修改一下代碼,讓任務(wù)組可以執(zhí)行預(yù)期的異步操作

    // 任務(wù)組
    dispatch_group_t group = dispatch_group_create();
    dispatch_queue_t group_queue = dispatch_queue_create("com.test.group", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_enter(group);
    dispatch_group_async(group, group_queue, ^{
        [self requestOneInfo:^{
            NSLog(@"one info done");
            dispatch_group_leave(group);
        }];
    });
    
    dispatch_group_enter(group);
    dispatch_group_async(group, group_queue, ^{
        [self requestOtherInfo:^{
            NSLog(@"other info done");
            dispatch_group_leave(group);
        }];
    });
    
    dispatch_group_notify(group, group_queue, ^{
        NSLog(@"all task done");
    });
// 打印达传,符合預(yù)期
2019-01-03 20:13:05.609618+0800 ThreadTest[4963:1290616] 當(dāng)前主線程
2019-01-03 20:13:05.609897+0800 ThreadTest[4963:1290656] get OneInfo start
2019-01-03 20:13:05.609923+0800 ThreadTest[4963:1290654] get OtherInfo start
2019-01-03 20:13:07.615273+0800 ThreadTest[4963:1290656] get OneInfo end
2019-01-03 20:13:07.615284+0800 ThreadTest[4963:1290654] get OtherInfo end
2019-01-03 20:13:07.615583+0800 ThreadTest[4963:1290654] other info done
2019-01-03 20:13:07.615583+0800 ThreadTest[4963:1290656] one info done
2019-01-03 20:13:07.615914+0800 ThreadTest[4963:1290654] all task done

NSOpreation

是GCD的一種封裝篙耗,需要使用子類。

任務(wù)隊(duì)列:NSOpreationQueue 相當(dāng)于一個(gè)線程池的概念宪赶,可以添加任務(wù)宗弯,設(shè)置最大并發(fā)數(shù)。

任務(wù)有幾種狀態(tài):ready搂妻,canceld蒙保,executing,finished欲主,asynchronous

任務(wù)可以很方便的添加依賴

我們可以使用系統(tǒng)提供了兩個(gè)子類創(chuàng)建NSOpreaion通過(guò)調(diào)用任務(wù)的start方法啟動(dòng)任務(wù)邓厕,會(huì)在當(dāng)前的線程同步執(zhí)行。

如果我們需要異步執(zhí)行扁瓢,通過(guò)創(chuàng)建隊(duì)列详恼,把任務(wù)添加到隊(duì)列即可。

    NSBlockOperation *op =  [NSBlockOperation blockOperationWithBlock:^{
      NSLog(@"任務(wù)執(zhí)行了");
    }];
    [op start];// 在當(dāng)前線程同步執(zhí)行
    
   NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [queue addOperation:op];// 異步執(zhí)行

如果任務(wù)需要設(shè)置依賴關(guān)系引几,調(diào)用任務(wù)的方法

-(void*)addDependency:(NSOperation *)op;

如果我們需要等待所有任務(wù)完成昧互,調(diào)用隊(duì)列的方法

-(void*)waitUntilAllOperationsAreFinished;

注意事項(xiàng):

線程之間共用進(jìn)程所有資源,當(dāng)多線程操作同一個(gè)變量的時(shí)候伟桅,可能會(huì)使得結(jié)果不正確敞掘。

因此要特別注意線程安全的問(wèn)題。

通常保證線程安全有很多種方式

  • 使用線程鎖
  • 使用串行隊(duì)列
  • 使用線程安全的類
  • 使用信號(hào)量或runloop使異步看起來(lái)像同步在執(zhí)行
  • 注意任務(wù)可能本身就是異步的
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贿讹,一起剝皮案震驚了整個(gè)濱河市渐逃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌民褂,老刑警劉巖茄菊,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疯潭,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡面殖,警方通過(guò)查閱死者的電腦和手機(jī)竖哩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)脊僚,“玉大人相叁,你說(shuō)我怎么就攤上這事×苫希” “怎么了增淹?”我有些...
    開(kāi)封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)乌企。 經(jīng)常有香客問(wèn)我虑润,道長(zhǎng),這世上最難降的妖魔是什么加酵? 我笑而不...
    開(kāi)封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任拳喻,我火速辦了婚禮,結(jié)果婚禮上猪腕,老公的妹妹穿的比我還像新娘冗澈。我一直安慰自己,他們只是感情好陋葡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布亚亲。 她就那樣靜靜地躺著,像睡著了一般脖岛。 火紅的嫁衣襯著肌膚如雪朵栖。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天柴梆,我揣著相機(jī)與錄音陨溅,去河邊找鬼。 笑死绍在,一個(gè)胖子當(dāng)著我的面吹牛门扇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播偿渡,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼臼寄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了溜宽?” 一聲冷哼從身側(cè)響起吉拳,我...
    開(kāi)封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎适揉,沒(méi)想到半個(gè)月后留攒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體煤惩,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年炼邀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魄揉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡拭宁,死狀恐怖洛退,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杰标,我是刑警寧澤兵怯,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站在旱,受9級(jí)特大地震影響摇零,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桶蝎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谅畅。 院中可真熱鬧登渣,春花似錦、人聲如沸毡泻。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)仇味。三九已至呻顽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丹墨,已是汗流浹背廊遍。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贩挣,地道東北人喉前。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像王财,于是被迫代替她去往敵國(guó)和親卵迂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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