线程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阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容