pthread2

来源:互联网 发布:和风天气 json解析 js 编辑:程序博客网 时间:2024/06/06 09:07
下面我们来看看这个demo

 

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

 

int myglobal;

 

void * thread_function(void * arg)

{

    int i,j;

    for (i=0; i<20; i++) {

        j=myglobal;

        j++;

        printf(".");

        fflush(stdout);

        sleep(1);

        myglobal=j;

    }

    return  NULL;

}

 

int main(int argc, const char * argv[])

{

    pthread_t mythread;

    int i;

    if (pthread_create(&mythread, NULLthread_functionNULL)) {

        printf("error creating thread");

        abort();

    }

    for (i=0; i<20; i++) {

        myglobal++;

        printf("o");

        fflush(stdout);

        sleep(1);

    }

    if (pthread_join(mythread, NULL)) {

        printf("error joining thread");

        abort();

    }

    printf("\nmyglobal equals %d\n",myglobal);

    return 0;

}

 

对于这个问题,我们知道是这个全局变量没有保护的问题,这样导致一个线程的更改覆盖了另外一个线程的改变。
那下面我们就对这个全局变量myglobal加锁。即在myglobal的范围上下加上lock和unlock,具体如下:

 

#include <stdio.h>

#include <pthread.h>

#include <unistd.h>

#include <stdlib.h>

 

int myglobal;

pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

void * thread_function(void * arg)

{

    int i,j;

    for (i=0; i<20; i++) {

        pthread_mutex_lock(&mymutex);

        j=myglobal;

        j++;

        printf(".");

        fflush(stdout);

        sleep(1);

        myglobal=j;

        pthread_mutex_unlock(&mymutex);

    }

    return  NULL;

}

 

int main(int argc, const char * argv[])

{

    pthread_t mythread;

    int i;

    if (pthread_create(&mythread, NULLthread_functionNULL)) {

        printf("error creating thread");

        abort();

    }

    for (i=0; i<20; i++) {

        pthread_mutex_lock(&mymutex);

        myglobal++;

        pthread_mutex_unlock(&mymutex);

        printf("o");

        fflush(stdout);

        sleep(1);

    }

    if (pthread_join(mythread, NULL)) {

        printf("error joining thread");

        abort();

    }

    printf("\nmyglobal equals %d\n",myglobal);

    return 0;

}

对于线程的运行我们一定不要假设哪个会在前面运行哪个会在后面运行,只要线程创建以后我们可以认为他们是同时运行的。

我们看下互斥对象的使用。

首先是初始化

    静态初始化给变量赋一个常数

 

    pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER;

    另外也可以动态的创建互斥对象,即像使用malloc一样动态分配,在这边我们使用

 

    int pthread_mutex_init(pthread_mutex_t *restrict, const pthread_mutexattr_t *restrict)

第一个参数是要初始化的互斥对象,这个指针已经分配好了一块内存,第二个参数是设定互斥量属性的,为空则为默认属性。

如果使用了pthread_mutex_init初始化了互斥对象,就要用pthread_mutex_destory来销毁,其参数为指向要销毁的互斥量。注意的是这边不会释放用来存储互斥量pthread_mutex_t的内存,也就是我们可以直接再用pthread_mutex_init来重新初始化被销毁的内存。

另外我们要注意的是不管是创建还是销毁,成功的时候返回的都是0.

 

使用

pthread_mutex_lock接受一个互斥对象的指针作为参数,将其锁定,如果该互斥对象已经锁定,则该调用者进入睡眠状态,如果函数返回,则唤醒当前线程。

pthread_mutex_unlock与上述配合使用,看到名字我们知道这个是解锁。

这里我们要明确的是一定要尽快对已经加锁的互斥对象进行解锁,以提高性能。

另外一定不要对没有加锁的互斥对象进行解锁,这样pthread_mutex_unlock会调用失败。

 

我们会考虑下一个问题就是,计算机要不停的监测这个互斥量的状态,改变状态之后要立即做出反应,这样是不可取的,因此也就是有了信号量这一说。

 

通过信号量来使线程进入睡眠状态或者唤醒这个线程。

 

0 0
原创粉丝点击