zoukankan      html  css  js  c++  java
  • linux 线程同步(二)

    信号量

    信号量是相互排斥锁的升级版把相互排斥锁中1变成了n。举个简单的样例:如果如今有10个人,有一部手机。这10个人都竞争来使用手机打电话这就是相互排斥锁。对于信号量,如今可能是有4部手机,这10个人都竞争来使用手机打电话。相比相互排斥锁信号量由1变成了4。信号量相也就是操作系统中pv操作,它广泛应用进程或者线程间的同步与相互排斥。

    相关库函数介绍

    #include <semaphore.h>//所需头文件
    //初始化信号量sem初始化的时候能够指定信号量的初始值,以及能否够在多进程间共享value表示要信号量初始值,pshared表示是否再多进程之前共享。

    0表示不在多进程间 共享,非0表示在多进程之间共享详细能够man sem_init //成功返回0,出错返回-1 int sem_init(sem_t *sem, int pshared, unsigned int value); int sem_wait(sem_t *sem)//相当于p操作 int sem_try_wait(sem_t *sem)//相当于p操作。在信号量值大于0时都能将信号量的值减一,与上面sem_wait的差别是,在信号值小于0时 int sem_post(sem_t *sem)//相当于v操作 int sem_getvalue(sem_t *sem)//用于得到信号量的值 int sem_destory(sem_t *sem) //释放信号量  


    信号量实例:生产者消费值

    #include<stdio.h>
    #include<stdlib.h>
    #include <pthread.h>
    #include <semaphore.h>
    #define BUFSIZE  10
    int buf[BUFSIZE];
    sem_t consumer_sem,producer_sem;
    void *consumer(void *arg)
    {
    	int c=0;
    	while(1)
    	{
    		sem_wait(&consumer_sem);//開始消费consumer_sem值减一
    		printf("consumer %d: %d
    ",c,buf[c]);//消费数据
    		c++;
    		c=c%BUFSIZE;
    	    sleep(1);//睡眠1s
    		sem_post(&producer_sem);//producer_sem值加1
    	}
    }
    void *producer(void *arg)
    {
    	int p=0;
    	while(1)
    	{
    		sem_wait(&producer_sem);//開始生产producer_sem值减一
    		buf[p]=rand() % 1000 + 1;//生产数据
    		printf("producer %d: %d
    ",p,buf[p]);
    		p++;
    		p=p%BUFSIZE;
    		sem_post(&consumer_sem);//consumer_sem值加1
    		
    	}
    }
    
    
    int main()
    {
    	
    	sem_init(&consumer_sem,0,0);
    	sem_init(&producer_sem,0,BUFSIZE);
    	
    	pthread_t pid,cid;
    	pthread_create(&pid,NULL,producer,NULL);
    	pthread_create(&cid,NULL,consumer,NULL);
    
    	pthread_join(pid, NULL);
    	pthread_join(cid, NULL);
    	sem_destroy(&consumer_sem);
    	sem_destroy(&producer_sem);
    	return 0;
    	
    }
    


    条件变量

    条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包含两个动作:一个线程等待"条件变量的条件成立"而挂起;还有一个线程使"条件成立"(给出条件成立信号)。

    为了防止竞争,条件变量的使用总是和一个相互排斥锁结合在一起。


    条件变量类型为 pthread_cond_t

    相关库函数简单介绍

    #include<pthread.h>
    int pthread_cond_destroy(pthread_cond_t *cond);//条件变量的资源释放
    int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);//条件变量的初始化
     
    

    #include<pthread.h>
    int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *mutex,
    const struct timespec *abstime);
    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
    //等待某个条件是否成立。对于timewait()函数除了等待以外。能够设置一个时长。 
    int pthread_cond_signal(pthread_cond_t *cond);//种情况是仅仅有一个线程收到后运行动作。

    //活动线程仅仅须要唤醒第一个正在睡眠的线程。如果您仅仅对队列加入了一个工作作业。

    那么仅仅须要唤醒一个工作程序线程(再唤醒其他线程是不礼貌的!

    ) int pthread_cond_broadcast(pthread_cond_t *cond);//通过广播的形式发给子线程消息。子线程竞争运行。

    不管哪种等待方式,都必须和相互排斥锁结合,以防止多个线程同一时候请求pthread_cond_wait()(或pthread_cond_timedwait())的竞争条件,且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列曾经,mutex保持锁定状态。并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被又一次加锁,以与进入pthread_cond_wait()前的加锁动作相应。


    #include <stdlib.h>
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    
    struct msg {
        struct msg *next;
        int num;
    };
    
    struct msg *head;
    /* 条件变量 */
    pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    void *consumer(void *p)
    {
        struct msg *mp;
        while(1)
    	{
            pthread_mutex_lock(&lock);
            /* pthread_cond_wait(&has_product, &lock);
             * 1.堵塞等待has_product被唤醒。
             * 2.释放相互排斥锁。 pthread_mutex_unlock(&lock)
             * 3.当被唤醒时。解除堵塞,而且又一次去申请获得相互排斥锁 pthread_mutex_lock(&lock)
             */
            while (head == NULL)
                pthread_cond_wait(&has_product, &lock);//等待
    
            mp = head;
            head = mp->next;
            pthread_mutex_unlock(&lock);
            printf("Consume %d
    ", mp->num);
            free(mp);
            sleep(rand() % 5);
        }
    }
    
    void *producer(void *p)
    {
        struct msg *mp;
        while(1)
    	{
            mp =(struct msg *)malloc(sizeof(struct msg));
            mp->num = rand() % 1000 + 1;
            printf("Produce %d
    ", mp->num);
            pthread_mutex_lock(&lock);
            mp->next = head;
            head = mp;
            pthread_mutex_unlock(&lock);
            /* pthread_cond_broadcast(&has_product) 唤醒等待队列上的全部线程*/
    		//发送信号,告诉消费者有产品了
            pthread_cond_signal(&has_product);
            sleep(rand() % 5);
        }
    }
    
    int main(int argc, char *argv[])
    {
        pthread_t pid, cid;
        srand(time(NULL));
        pthread_create(&pid, NULL, producer, NULL);
        pthread_create(&cid, NULL, consumer, NULL);
        pthread_join(pid, NULL);
        pthread_join(cid, NULL);
        return 0;
    }
    



  • 相关阅读:
    sublime text3安装package control插件图文教程
    conda创建新环境
    常用的vscode插件安装
    数组合并组合
    内核软死锁
    Ubuntu分区格式化并挂载新增磁盘方法
    Linux如何列出svn一个文件夹下的所有文件
    C++ UTF-8和GBK相互转化
    Linux shell如何用正则表达式匹配分组数据
    如何对接jsoncpp?
  • 原文地址:https://www.cnblogs.com/llguanli/p/6903124.html
Copyright © 2011-2022 走看看