線程thread(day06)

作業1

司機: 接收售票員關門信號-->開車 //SIGUSR1
接收到站信號-->停車 //SIGINT
發送開門信號給售票員-->等待關門信號 //pause() 掛起進程
售票員:發送關門信號
接收開門信號-->開門 //SIGUSR2

#include <stdio.h>
#include <string.h>
#include <unistd.h>  //fork ()
#include <stdlib.h>
#include <sys/types.h> //kill()
#include <signal.h>  //signal()

pid_t pid = -1;

//司機:到站停車  --> SIGINT  ctrl+c
//      關門開車  --> SIGUSR1
void handleDriver(int sig)
{
    if (SIGINT == sig)
    {
        printf("到站了...\\n");
        sleep(1);
        printf("司機開始停車...\\n");
        sleep(1);
        int ret = 0;
        ret = kill(pid, SIGUSR2);  //發送信號給售票員讓她開門
        if (-1 == ret)
        {
            perror("kill");
        }
    }
    else if (SIGUSR1 == sig)
    {
        printf("司機開始開車...\\n");
        sleep(1);
        printf("車正在跑...\\n");   
        sleep(1);
    }
}
//售票員:開門 -->SIGUSR2
void handleConductor(int sig)
{
    if (SIGUSR2 == sig)
    {
        printf("售票員開門...\\n");
        sleep(1);
        printf("乘客上車...\\n");
        sleep(1);
        printf("售票員關門...\\n");
        sleep(1);
        kill(getppid(), SIGUSR1);  //售票員發送信號給司機開車
    }
}

int main(void)
{
    pid = fork();
    if (pid > 0)  //driver
    {
        signal(SIGINT, handleDriver);
        signal(SIGUSR1, handleDriver);
        printf("司機等待售票員做好開車準備...\\n");
        while (1)
        {
            pause();
        }   
    }
    else if (0 == pid)  //conductor
    {
        signal(SIGINT, SIG_IGN);
        signal(SIGUSR2, handleConductor);
        sleep(1);
        //發送一個開車信號讓其開車
        kill(getppid(), SIGUSR1);
        while (1)
        {
            pause();    
        }   
    }
    else if (-1 == pid)
    {
        perror("fork");
        return -1;
    }

    return 0;
}

運行結果:


1.PNG

創建線程

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

void *thread_run(void *arg)
{
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

運行結果:

2.PNG

pthread_arg.c

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

typedef struct Student
{
    int iId;
    char caName[32];
    float fScore;
}Student;

void *thread_run(void *arg)
{
    while (1)
    {
        //printf("this is thread_run...arg = %d\\n", *(int *)arg);
        //printf("this is thread_run...arg = %d\\n", (int)arg);
        Student *pStu = (Student *)arg;
        printf("id:%d, name:%s, score:%.2f\\n"
               , pStu->iId, pStu->caName, pStu->fScore);
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    int iArg = 1888;
    //ret = pthread_create(&thread, NULL, thread_run, &iArg);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)iArg);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)1888);
    Student stu = {1001, "zhangsan", 89};
    ret = pthread_create(&thread, NULL, thread_run, &stu);
    //ret = pthread_create(&thread, NULL, thread_run, (void *)stu);  //error
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        pause();
    }

    return 0;
}

運行結果:


1.PNG

pthread_cancel_exit.c

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

void *thread_run(void *arg)
{
    //在線程函數中調用pthread_setcancelstate來設置
    //不同意結束線程請求,阻塞線程結束請求
    //直到線程允許接收線程結束請求
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
        //break;
        //結束所屬線程
        //pthread_exit(NULL);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    sleep(3);
    //發送一個結束線程請求給指定的線程
    //默認情況下,線程會同意該結束線程請求
    //還可以設置不同意
    //pthread_cancel(thread);
    
    //若存在主線程中,如果含有其他線程存在,
    //則阻塞等待線程的結束

    //若沒有其他線程,則結束程序
    pthread_exit(NULL);
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

運算結果:


1.PNG

pthread_exit.c

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>  //sleep()
#include <stdlib.h>  //exit()

//一個進程創建線程后,創建的線程從屬于該進程
//不獨立于進程,共享進程的所有資源

//線程是最小的執行單元,
//若一個進程沒有創建線程,我們既可以把它看做是進程,也可以是相當于線程
//若一個進程創建線程后,我們可以將該進程稱之為主線程
//一個進程可以創建多個線程,線程之間資源共享
void *thread_run(void *arg)
{
    int i = 0;
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
        i++;
        if (5 == i)
        {
            //使用return 只能結束當前線程
            //return NULL;

            //會將該線程所屬的進程掛掉,當然線程也會掛掉
            exit(1);
        }
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

運算結果:


1.PNG

pthread_join.c

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

void *thread_run(void *arg)
{
    while (1)
    {
        printf("this is thread_run...\\n");
        sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    //等待線程結束,若線程在運行,則阻塞等待
    //若線程結束,立即返回
    //第一個參數:要等待的線程
    //第二個參數:要來獲得線程的返回值
    pthread_join(thread, NULL);
    while (1)
    {
        printf("this is main...\\n");
        sleep(1);
    }

    return 0;
}

運算結果:

1.PNG

pthread_mutex.c

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

pthread_mutex_t mutex;   //互斥量--鎖

int g_iData = 0;

void *thread_run(void *arg)
{
    while (1)
    {
        //使用pthread_mutex_lock和pthread_mutex_unlock
        //使它們之間的語句合成原子操作

        //若其他線程沒有釋放該互斥量
        //則本線程阻塞等待
        //pthread_mutex_lock(&mutex);
        //pthread_mutex_trylock(&mutex);
        ++g_iData;
        printf("thread:data = %d\\n", g_iData);
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

int main(void)
{
    //初始化互斥量,NULL表示使用默認屬性初始化該互斥量
    pthread_mutex_init(&mutex, NULL);
    
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    while (1)
    {
        pthread_mutex_lock(&mutex);
        ++g_iData;
        printf("main:data = %d\\n", g_iData);
        pthread_mutex_unlock(&mutex);
    }

    return 0;
}

運算結果:

2.PNG

pthread_share

#include <pthread.h>  //pthread_create()

#include <stdio.h>
#include <string.h> //strerror()
#include <errno.h>  //errno
#include <unistd.h>

int g_iData = 999;

void *thread_run(void *arg)
{
    //while (1)
    {
        printf("this is thread_run...iData = %d\\n", g_iData);
        g_iData++;
        //sleep(1);
    }

    return NULL;
}

int main(void)
{
    pthread_t thread;
    int ret = 0;
    ret = pthread_create(&thread, NULL, thread_run, NULL);
    if (0 != ret)
    {
        printf("errno:%d, error:%s\\n", ret, strerror(ret));
        return -1;
    }
    sleep(2);
    //  while (1)
    {
        printf("this is main...iData = %d\\n", g_iData);
//      sleep(1);
    }

    return 0;
}

運算結果:

1.PNG

read_stu

#include <stdio.h>
#include <unistd.h>  //write()  read()
#include <errno.h>   //errno
#include <string.h>  //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <pthread.h> //pthread_create

pthread_mutex_t mutex;

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_re LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_RDONLY | O_CREAT
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int g_iSign = 0;

void *read_thread(void *arg)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        int ret = -1;
        Student *pStu = (Student *)arg;
        while (1)
        {
            if (0 == g_iSign)
            {
                pthread_mutex_lock(&mutex);
                memset(pStu, '\\0', sizeof(Student));
                ret = read(fd, pStu, sizeof(Student));
                if (0 == ret)
                {
                    printf("reached the file end\\n");
                    pthread_mutex_unlock(&mutex);
                    g_iSign = 1;
                    break;
                }
                else if (-1 == ret)
                {
                    printf("read error:%s\\n", strerror(errno));
                    pthread_mutex_unlock(&mutex);
                    g_iSign = 1;
                    break;
                }
                pthread_mutex_unlock(&mutex);
                g_iSign = 1;
            }
        }
        close(fd);
    }   

    return NULL;
}

void *print_thread(void *arg)
{
    Student *pStu = (Student *)arg;
    int i = 0;
    while (1)
    {
        if (1 == g_iSign)
        {
            pthread_mutex_lock(&mutex);
            if (0 == pStu->iId)
            {
                pthread_mutex_unlock(&mutex);
                break;
            }
        
            printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
                   , pStu->iId, pStu->caName
                   , pStu->cSex, pStu->fScore);
        
            pthread_mutex_unlock(&mutex);
            g_iSign = 0;
        }
    }

    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, NULL);

    Student stu;
    pthread_t pthr_read;
    pthread_t pthr_show;

    pthread_create(&pthr_read, NULL, read_thread, &stu);
    pthread_create(&pthr_show, NULL, print_thread, &stu);

    pthread_join(pthr_read, NULL);
    pthread_join(pthr_show, NULL);

    return 0;
}

運算結果:


3.PNG

write_stu.c

#include <stdio.h>
#include <unistd.h>  //write()
#include <errno.h>   //errno
#include <string.h>  //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int main(void)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        Student stu[6] = {{1001, "zhangsan", 'f', 99}
                          , {1002, "lisi", 'm', 79}
                          , {1003, "wangwu", 'f', 89}
                          , {1004, "zhaoliu", 'm', 69}
                          , {1005, "xiaoqi", 'm', 79}
                          , {1006, "laoba", 'f', 89}};
        int ret = -1;
        int i = 0;
        for (; i < 6; i++)
        {
            ret = write(fd, stu+i, sizeof(Student));
            if (-1 == ret)
            {
                printf("write error: %s\\n", strerror(errno));
            }
            else
            {
                printf("write %d bytes to file\\n", ret);
            }
        }
    }   

    return 0;
}
1.PNG

sem_read_stu.c

#include <stdio.h>
#include <unistd.h>  //write()  read()
#include <errno.h>   //errno
#include <string.h>  //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <pthread.h> //pthread_create
#include <semaphore.h>  

pthread_mutex_t mutex;

sem_t read_sem;  //整形 
sem_t show_sem;

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_RDONLY | O_CREAT
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

void *read_thread(void *arg)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        int ret = -1;
        Student *pStu = (Student *)arg;
        while (1)
        {
            //如果read_sem大于0,接著往下執行,并且將該變量減一
            //如果read_sem等于0,則阻塞,直到該值大于0
            sem_wait(&read_sem);
            
            pthread_mutex_lock(&mutex);
            
            memset(pStu, '\\0', sizeof(Student));
            ret = read(fd, pStu, sizeof(Student));
            if (0 == ret)
            {
                printf("reached the file end\\n");
                pthread_mutex_unlock(&mutex);
                sem_post(&show_sem);
                break;
            }
            else if (-1 == ret)
            {
                printf("read error:%s\\n", strerror(errno));
                pthread_mutex_unlock(&mutex);
                sem_post(&show_sem);
                break;
            }
            pthread_mutex_unlock(&mutex);
            //將信號量的值加一
            sem_post(&show_sem);
        }
    }
    close(fd);

    return NULL;
}

void *print_thread(void *arg)
{
    Student *pStu = (Student *)arg;
    int i = 0;
    while (1)
    {
        {
            //如果show_sem大于0,接著往下執行,并且將該變量減一
            //如果show_sem等于0,則阻塞,直到該值大于0
            sem_wait(&show_sem);
            pthread_mutex_lock(&mutex);
            if (0 == pStu->iId)
            {
                pthread_mutex_unlock(&mutex);
                sem_post(&read_sem);
                break;
            }
        
            printf("id:%d, name:%s, sex:%c, score:%.1f\\n"
                   , pStu->iId, pStu->caName
                   , pStu->cSex, pStu->fScore);
        
            pthread_mutex_unlock(&mutex);
            //將信號量的值加一
            sem_post(&read_sem);
        }
    }

    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, NULL);

    //初始化信號量
    sem_init(&read_sem, 0, 1);  //將read_sem值置為1
    sem_init(&show_sem, 0, 0);  //將show_sem值置為0

    Student stu;
    pthread_t pthr_read;
    pthread_t pthr_show;

    pthread_create(&pthr_read, NULL, read_thread, &stu);
    pthread_create(&pthr_show, NULL, print_thread, &stu);

    pthread_join(pthr_read, NULL);
    pthread_join(pthr_show, NULL);

    return 0;
}

運算結果:


1.PNG

write_stu.c

#include <stdio.h>
#include <unistd.h>  //write()
#include <errno.h>   //errno
#include <string.h>  //strerror()
/*open()*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define NAME_LEN 32
typedef struct Student
{
    int iId;
    char caName[NAME_LEN];
    char cSex;
    float fScore;

}Student;

int myOpen(const char *pathname)
{
    int fd  = -1;
    if (NULL != pathname)
    {
        fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC
                  , S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
        if (-1 == fd)
        {
            printf("open error: %s\\n", strerror(errno));
        }
    }
    return fd;
}

int main(void)
{
    int fd = -1;
    fd = myOpen("stu.info");
    if (-1 != fd)
    {
        Student stu[6] = {{1001, "zhangsan", 'f', 99}
                          , {1002, "lisi", 'm', 79}
                          , {1003, "wangwu", 'f', 89}
                          , {1004, "zhaoliu", 'm', 69}
                          , {1005, "xiaoqi", 'm', 79}
                          , {1006, "laoba", 'f', 89}};
        int ret = -1;
        int i = 0;
        for (; i < 6; i++)
        {
            ret = write(fd, stu+i, sizeof(Student));
            if (-1 == ret)
            {
                printf("write error: %s\\n", strerror(errno));
            }
            else
            {
                printf("write %d bytes to file\\n", ret);
            }
        }
    }   

    return 0;
}

運算結果:


1.PNG

think-eat.c

/*semget()*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

#include <string.h> //perror()
#include <unistd.h> //fork()
#include <stdio.h>  //printf()

union semun 
{
    int val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT,IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */                                                      
};

#if 0
int semop(int semid, struct sembuf *sops, unsigned nsops);

參數
semid:信號集的識別碼,可通過semget獲取。
sops:指向存儲信號操作結構的數組指針,信號操作結構的原型如下
struct sembuf
{
        unsigned short sem_num; /* semaphore number */
        short sem_op; /* semaphore operation */
        short sem_flg; /* operation flags */
};
這三個字段的意義分別為:
sem_num:操作信號在信號集中的編號,第一個信號的編號是0。

sem_op:
   1, 如果其值為正數,該值會加到現有的信號內含值中。
      通常用于釋放所控資源的使用權;
   2, 如果sem_op的值為負數,而其絕對值又大于信號的現值,
      操作將會阻塞,直到信號值大于或等于sem_op的絕對值。
      通常用于獲取資源的使用權;
   3, 如果sem_op的值為0,如果沒有設置IPC_NOWAIT,
      則調用該操作的進程或者線程將暫時睡眠,直到信號量的值為0;      否則,進程或者線程不會睡眠,函數返回錯誤EAGAIN。

sem_flg:信號操作標志,可能的選擇有兩種
   1, IPC_NOWAIT //對信號的操作不能滿足時,semop()不會阻塞,
      并立即返回,同時設定錯誤信息。
   2, SEM_UNDO //程序結束時(不論正常或不正常),
      保證信號值會被重設為semop()調用前的值。
      這樣做的目的在于避免程序在異常情況下結束時
      未將鎖定的資源解鎖,造成該資源永遠鎖定。

nsops:信號操作結構的數量,恒大于或等于1。
#endif

void getChopsticks(int iNum, int *semfd)
{
    int iLeft = iNum;
    int iRight = (iNum + 1)%5;

    struct sembuf semope[2] = {{iLeft, -1, 0}
                               , {iRight, -1, 0}};
    semop(*semfd, semope, 2);
}

void putChopsticks(int iNum, int *semfd)
{
    int iLeft = iNum;
    int iRight = (iNum + 1)%5;

    struct sembuf semope[2] = {{iLeft, 1, 0}
                               , {iRight, 1, 0}};
    semop(*semfd, semope, 2);
}

void thinkAndEat(int iNum, int *semfd)
{
    while (1)
    {
        printf("%d say: I am thinking...\\n", iNum);
        /*拿筷子吃飯*/
        getChopsticks(iNum, semfd);
        sleep(1);
        printf("%d say: I am eatting...\\n", iNum);
        /*放下筷子*/
        putChopsticks(iNum, semfd);
        printf("%d say: I am put chopsticks...\\n", iNum);
        sleep(1);
    }
}

int main(void)
{
    int semfd = -1;
    //獲得信號量集的標識,若信號量集不存在則創建
    semfd = semget(0x1024, 5, IPC_CREAT | 0777);
    if (-1 == semfd)
    {
        perror("semget");
        return -1;
    }

    //對信號集中的信號量賦值
    union semun sem;
    sem.val = 1;
    int i = 0;
    for (; i < 5; i++)
    {
        if (-1 == semctl(semfd, i, SETVAL, sem))
        {
            perror("semctl");
            return -1;
        }
    }

    //創建五個哲學家進程
    int num = 0;  //表示第幾個哲學家
    pid_t pid = -1;
    for (i = 0; i < 4; i++)
    {
        pid = fork();
        if (pid > 0)  //parent
        {
            num = 4;
        }
        else if (0 == pid) //child
        {
            num = i;
            break;
        }
        else if (-1 == pid) //error
        {
            return -1;
        }
    }
    thinkAndEat(num, &semfd);

    return 0;
}

運算結果:

2.PNG
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容