美文网首页
20.线程同步

20.线程同步

作者: 陈忠俊 | 来源:发表于2020-05-04 17:57 被阅读0次

    1.mutex互斥锁

    常用的互斥锁函数

    pthread_mutex_init(3) #初始化锁,返回0
    pthread_mutex_destroy(3) #指定要销毁锁的地址,成功返回0
    pthread_mutex_lock(3) # 如果锁被其他线程占用,阻塞等待,直到占用该锁的线程释放锁。否则,立即上锁并返回
    pthread_mutext_trylock(3) #尝试加锁,如不能,返回错误。可以,立即加锁并返回
    pthread_mutext_unlock(3) #释放锁
    

    代码实现,两个线程交替计算

    #include<stdio.h>
    #include<pthread.h>
    #include<unistd.h>
    #include<sys/types.h>
    
    
    pthread_mutex_t mutex;
    int value = 0;
    
    void *temp(void *arg){
        int tmp;
        for(int i = 0; i < 5000; i++){
            //lock now
            pthread_mutex_lock(&mutex);
            tmp = value;
            tmp++;
            printf("threadId: %lu\ttmp = %d\n", pthread_self(), tmp);
            value = tmp;
            pthread_mutex_unlock(&mutex);
        }
        return NULL;
    }
    
    int main(void){
        pthread_mutex_init(&mutex, NULL);
        pthread_t thread_1, thread_2;
        pthread_create(&thread_1, NULL, temp, NULL);
        pthread_create(&thread_2, NULL, temp, NULL);
        pthread_join(thread_1, NULL);
        pthread_join(thread_2, NULL);
    
        pthread_mutex_destroy(&mutex);
    
        return 0;
    }
    

    2.条件变量

    常用函数

    pthread_cond_init(3) #初始化一个条件变量
    pthread_cond_destroy(3) # 销毁条件变量的地址
    pthread_cond_signal(3) # 如果有多个线程等待条件变量为真,从其中选出一个执行。如果没有线程等待条件变量为真,什么都不做。
    pthread_cond_broadcast(3) #通知多个有等待条件变量为真的线程执行。如果没有条件变量为真,则什么都不做。
    pthread_cond_wait(3) # 原子的解锁并等待条件变量为真。当条件变量为真的时候,重新获取mutex锁
    pthread_cond_timewait(3) 
    

    生产者消费者模型

    #include <t_stdio.h>
    #include <pthread.h>
    #include <time.h>
    #include <stdlib.h>
    #include <unistd.h>
    //定义链表节点的类型
    typedef struct node{
        int data;
        struct node *next;
    }node_t;
    
    node_t *head=NULL;
    pthread_mutex_t mutex;//定义锁类型的变量
    pthread_cond_t cond;//定义条件变量
    //生产者线程
    void *product(void *arg){
        node_t *new;
        while(1){
            //生产一个新节点
            new=(node_t *)malloc(sizeof(node_t));
            new->data=rand()%1000+1;
            new->next=NULL;
            printf("p:%d\n",new->data);
            //加锁
            pthread_mutex_lock(&mutex);
            
            new->next=head;
            head=new;
            //解锁
            pthread_mutex_unlock(&mutex);
           
            pthread_cond_signal(&cond);
            sleep(rand()%3+1);    
        }
        return NULL;
    }
    //消费者线程
    void *consume(void *arg){
        node_t *tmp;
        while(1){
            //加锁
            pthread_mutex_lock(&mutex);
            while(head==NULL)
                pthread_cond_wait(&cond,&mutex);
                //重新获取mutex锁
            tmp=head;
            head=head->next;
            //解锁
            pthread_mutex_unlock(&mutex);
            printf("c:%d\n",tmp->data);
            //消费该节点
            free(tmp);
            tmp=NULL;
            sleep(rand()%3+1);    
        }
        return NULL;
    }
    
    int main(void){
        srand(time(NULL));
        //初始化mutex变量
        pthread_mutex_init(&mutex,NULL);
        pthread_cond_init(&cond,NULL);
        //创建两个线程 生产者  消费者
        pthread_t pid,cid;
        pthread_create(&pid,NULL,product,NULL);
        pthread_create(&cid,NULL,consume,NULL);
        //等待线程的汇合
        pthread_join(pid,NULL);
        pthread_join(cid,NULL);
        //销毁mutex变量
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
        
        return 0;
    }
    

    3.信号量

    常用的函数

    sem_init # 初始化一个匿名的信号量
    sem_destroy # 销毁信号量
    sem_post # 解锁信号量,信号量+1,如果有线程或者进程调用阻塞在该信号量,则被唤醒,继续锁定信号量(-1)
    sem_wait # 信号量值减1操作。如果当前信号量的值为0,阻塞等待直到其他进程或线程使该信号量大于0为止
    sem_trywait # 尝试一次操作,如果信号量的值为0,立即返回,返回错误
    sem_timedwait # 指定等待的时间,超时返回超时错误
    

    信号量控制的生产者和消费者模型

    #include <pthread.h>
    #include <t_stdio.h>
    #include <unistd.h>
    #include <time.h>
    #include <stdlib.h>
    #include <semaphore.h>
    typedef int que_t[7];
    sem_t p,c; 
    que_t que;//定义队列
    
    //生产者线程
    void *product(void *arg){
        int index=0;
        while(1){
            sem_wait(&p);//如果p的值=0,阻塞
            que[index]=rand()%500+1;
            printf("p:%d\n",que[index]);
            index=(index+1)%7;
            sem_post(&c);//可消费的数量加1
            sleep(rand()%3+1);
        }
    }
    //消费者线程
    void *consume(void *arg){
        int index=0;
        int tmp;
        while(1){
            sem_wait(&c);
            tmp=que[index];
            que[index]=-1;
            printf("c:%d\n",tmp);
            index=(index+1)%7;
            sem_post(&p);//可生产数量加1
            sleep(rand()%3+1);
        }
    }
    int main(void){
        srand(time(NULL));
        //初始化信号量
        sem_init(&p,0,7);
        sem_init(&c,0,0);
        //创建两个线程,分别用于生产者和消费者
        pthread_t pid,cid;
        pthread_create(&pid,NULL,product,NULL);
        pthread_create(&cid,NULL,consume,NULL);
        //阻塞等待线程汇合
        pthread_join(pid,NULL);
        pthread_join(cid,NULL);
        //销毁信号量
        sem_destroy(&p);
        sem_destroy(&c);
        return 0;
    }
    
    

    相关文章

      网友评论

          本文标题:20.线程同步

          本文链接:https://www.haomeiwen.com/subject/ceryghtx.html