zoukankan      html  css  js  c++  java
  • Linux C —— 多线程

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。

    http://www.cnblogs.com/shijiaqi1066/p/5769417.html

    线程基础

    创建线程

    pthread_create

    #include <pthread.h>
    int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void),  void *restrict arg);

    【参数】

    • tidp:传入函数,该函数会把创建的线程指针赋值给该参数。
    • attr:线程属性。
    • start_rtn:启动线程的函数指针。
    • arg:运行函数的参数。

    【返回值】成功,返回0;出错,返回-1。

    线程挂起

    pthread_join

    #include <pthread.h>
    int pthread_join( pthread_t thread, void **value_ptr);

    让当前线程在等待指定线程执行完后再继续执行。

    参数:

    • thread:等待退出线程的线程号。
    • value_ptr:退出线程的返回值。

    线程退出

    pthread_exit

    #include <pthread.h>
    void pthread_exit(void *rval_ptr);

    退出当前线程。该函数用于线程函数主动退出,而不是让其他线程退出。

    获取当前线程id

    pthread_self

    #include <pthread.h>
    pthread_t pthread_self(void);

    获取当前线程。线程ID由是pthread_t类型表示。

    判断线程是否相等

    pthread_equal

    #include <pthread.h>
    int pthread_equal(pthread_t tid1, pthread_t tid2);

    检查两个pthread是否相等。

    在不同的系统下,pthread_t的类型是不同的,比如在ubuntn下,是unsigned long类型,而在solaris系统中,是unsigned int类型。而在FreeBSD上才用的是结构题指针。 所以不能直接使用==判读,而应该使用pthread_equal来判断。


    例:创建线程

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    // 线程一
    void thread_1(void) {
        int i = 0;
        for(i = 0; i <= 6; i++) {
            printf("This is a pthread_1.
    ");
            if(i == 2) {
                pthread_exit(0);
            }
            sleep(1);
        }
    }
    
    // 线程二
    void thread_2(void) {
        int i;
        for(i = 0; i < 3; i++) {
            printf("This is a pthread_2.
    ");
        }
        pthread_exit(0);
    }
    
    int main(void) {
        pthread_t id_1, id_2;
        int ret;
    
        /*创建线程一*/
        ret=pthread_create(&id_1, NULL, (void  *) thread_1, NULL);
        if(ret != 0) {
            printf("Create pthread error!
    ");
            return -1;
        }
    
        /*创建线程二*/
        ret=pthread_create(&id_2, NULL, (void  *) thread_2, NULL);
        if(ret != 0) {
            printf("Create pthread error!
    ");
            return -1;
        }
    
        /*等待线程结束*/
        pthread_join(id_1, NULL);
        pthread_join(id_2, NULL);
        return 0;
    }

    线程执行函数的返回值

    • pthread_exit(void *ret)
    • pthread_join(pthread_t id, void **ret)

    函数退出时,由pthread_exit函数退出,并用ret传出真正的返回值。外部函数若想接受到该参数,使用pthread_join的第二个参数来接收。

    回收线程资源

    pthread_detach

    #include <pthread.h>
    int pthread_detach(pthread_t);

    线程分离。

    Linux的线程有两种状态:

    • joinable
    • unjoinable

    默认线程是joinable的,则当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符(总计8K多)。只有对该线程调用了pthread_join之后这些资源才会被释放。

    线程的unjoinable状态可以在pthread_create时指定,也可以在线程创建后在线程中pthread_detach自己, 确保资源的释放。如:pthread_detach(pthread_self())。

    一般的回收线程有两种方法:

    方法一:使用pthread_detach让线程自动回收资源。

    pthread_t tid;
    int status = pthread_create(&tid, NULL, ThreadFunc, NULL);
    if(status != 0){ perror("pthread_create error");
    }
    pthread_detach(tid);

    方法二:使用thread_join让下一个线程回收当前线程。


    互斥量(锁)

    创建互斥量

    静态初始化互斥量

    PTHREAD_MUTEX_INITIALIZER

    pthread_mutex_t theMutex;
    pthread_mutex_t result = PTHREAD_MUTEX_INITIALIZER;

    动态初始化互斥量

    pthread_mutex_init

    #include <pthread.h>
    int  pthread_mutex_init(pthread_mutex_t  *restrict_mutex,const pthread_mutextattr_t *restrict attr)

    销毁锁

    pthread_mutex_destroy

    #include <pthread.h>
    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    使用完后释放。

    加锁

    pthread_mutex_lock

    #include <pthread.h>
    int pthread_mutex_lock(pthread_mutex_t *mutex);

    尝试加锁

    pthread_mutex_trylock

    #include <pthread.h>
    int pthread_mutex_trylock( pthread_mutex_t *mutex );

    加锁,但是与pthread_mutex_lock不一样的是当锁已经在使用的时候,返回为EBUSY,而不是挂起等待。

    在一定时间内加锁

    pthread_mutex_timedlock

    #include <pthread.h>
    int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout); 

    尝试lock,abs_timeout时间内仍被锁定,返回ETIMEOUT错误。timespec是超时时间,它用秒和纳秒来描述时间。

    解锁

    pthread_mutex_unlock

    #include <pthread.h>
    pthread_mutex_unlock(pthread_mutex_t *mutex);

    释放锁。

    例:两个线程各自加1。

    #include <pthread.h>
    #include <stdio.h>
    
    void add_1(void *arg);
    pthread_mutex_t mutex;
    
    int main() {
        int i = 10;
    
        // 声明线程
        pthread_t thread1,thread2;
    
        // 初始化锁
        pthread_mutex_init(&mutex,NULL);
    
        // 创建线程
        int rc1 = pthread_create(&thread1, NULL, (void *)add_1, &i);
        if(rc1 != 0){
            printf("thread-1 create failed: %d
    ",rc1);
        }
    
        // 创建线程
        int rc2 = pthread_create(&thread2, NULL, (void *)add_1, &i);
        if(rc2 != 0){
            printf("thread-2 create failed: %d
    ",rc1);
        }
    
        // 等待线程
        pthread_join(thread1,NULL);
        pthread_join(thread2,NULL);
    
        printf("i = %d",i);   // 打印输出 i = 210
    
        return 0;
    }
    
    // 线程运行函数
    void add_1(void *arg){
        int *i = (int *)arg;
        for(int n=0;n<100;n++){
            pthread_mutex_lock(&mutex);
            (*i)++;
            pthread_mutex_unlock(&mutex);
        }
        pthread_exit(NULL);
    }

    读写互斥量(读写锁)

     待写


    条件锁

    静态创建

    PTHREAD_COND_INITIALIZER

    #include <pthread.h>
    pthread_cond_t my_condition = PTHREAD_COND_INITIALIZER;

    动态创建

    pthread_cond_init

    #include <pthread.h>
    int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

    销毁

    pthread_cond_destroy

    #include <pthread.h>
    int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);

    等待

    pthread_cond_wait

    #include <pthread.h>
    int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
    int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

    触发

    pthread_cond_signal

    #include <pthread.h>
    int pthread_cond_signal(pthread_cond_t *cond);
    int pthread_cond_broadcast(pthread_cond_t *cond);

    例:生产者消费者

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "block_queue.h"
    
    #define BLOCK_POOL_SIZE 10
    
    void producer(void *arg);
    void customer(void *arg);
    
    int main() {
        int pthread_ret;
        pthread_t producer_thread_0,producer_thread_1,customer_thread;
        List *plist = block_queue_create(BLOCK_POOL_SIZE);
    
        pthread_ret = pthread_create(&producer_thread_0,NULL,(void *)producer,plist);
        if(pthread_ret!=0){
            puts("生产者线程创建失败");
            return EXIT_FAILURE;
        }
    
        pthread_ret = pthread_create(&producer_thread_1,NULL,(void *)producer,plist);
        if(pthread_ret!=0){
            puts("生产者线程创建失败");
            return EXIT_FAILURE;
        }
    
        pthread_ret = pthread_create(&customer_thread,NULL,(void *)customer,plist);
        if(pthread_ret!=0){
            puts("消费者线程创建失败");
            return EXIT_FAILURE;
        }
    
        // 主线程等待.
        pthread_join(producer_thread_0,NULL);
        pthread_join(producer_thread_1,NULL);
        pthread_join(customer_thread,NULL);
    
        block_queue_destroy(plist);
        return EXIT_SUCCESS;
    }
    
    void producer(void *arg){
        List *plist = (List *)arg;
        for (int i = 0; i < 40; i++) {
            block_queue_push(plist,i);
            printf("生产数据:%d
    ",i);
        }
    
        printf("---- 生产结束 ----
    ");
        pthread_exit(NULL);
    }
    
    void customer(void *arg){
        int data;
        List *plist = (List *)arg;
        for (int i = 0; i < 80; i++) {
            block_queue_pop(plist,&data);
            printf("消费数据:%d
    ",data);
        }
    
        printf("---- 消费结束 ----
    ");
        pthread_exit(NULL);
    }

    block_queue.h

    //
    // Created by shijiaqi on 16/11/22.
    //
    #include <pthread.h>
    
    typedef struct list_node{
        int data;
        struct node *next_node;
    } ListNode;
    
    typedef struct list{
        ListNode *firstNode;
        int size;
        int full_size;
        pthread_mutex_t mutex;
        pthread_cond_t cond_for_producer;
        pthread_cond_t cond_for_customer;
    } List;
    
    List * block_queue_create(int full_size);
    
    void block_queue_destroy(List *plist);
    
    void block_queue_push(List *plist,int data);
    
    int block_queue_pop(List *plist,int *p_data);

    block_queue.c

    //
    // Created by shijiaqi on 16/11/22.
    //
    #include "block_queue.h"
    #include <stdlib.h>
    #include <stdio.h>
    
    List * block_queue_create(int full_size){
        // 分配内存
        List *plist = malloc(sizeof(List));
        plist->full_size = full_size;
        plist->size = 0;
        plist->firstNode = NULL;
    
        // 初始化锁与条件等待.
        pthread_mutex_init(&(plist->mutex),NULL);
        pthread_cond_init(&(plist->cond_for_customer),NULL);
        pthread_cond_init(&(plist->cond_for_producer),NULL);
    
        return plist;
    }
    
    void block_queue_destroy(List *plist){
        int data = 0;
        int ret = 0;
    
        // 销毁所有数据。
        while(ret==0){
            if(plist->size > 0) {
                ret = block_queue_pop(plist, &data);
            }else{
                break ;
            }
        }
    
        // 销毁锁与条件等待
        pthread_cond_destroy(&(plist->cond_for_producer));
        pthread_cond_destroy(&(plist->cond_for_customer));
        pthread_mutex_destroy(&(plist->mutex));
    
        // 释放内存
        free(plist);
    }
    
    void block_queue_push(List *plist,int data) {
        // lock
        pthread_mutex_lock(&(plist->mutex));
    
        while(plist->size>=plist->full_size){
            printf("队列已满,生产者阻塞。目前仓储数量:%d
    ",plist->size);
            pthread_cond_wait(&(plist->cond_for_producer),&(plist->mutex));
        }
    
        ListNode *curNode = plist->firstNode;
        if(curNode == NULL) {
            ListNode *new_node = malloc(sizeof(ListNode));
            new_node->next_node = NULL;
            new_node->data = data;
            plist->firstNode = new_node;
            plist->size++;
    
            printf("队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:%d
    ",plist->size);
            pthread_cond_signal(&(plist->cond_for_customer));
    
            // unlock
            pthread_mutex_unlock(&(plist->mutex));
            return ;
        }
    
        ListNode *lastNode = curNode;
        curNode = (ListNode *)curNode->next_node;
        for(;;){
            if(curNode==NULL) {
                curNode = malloc(sizeof(ListNode));
                curNode->next_node = NULL;
                curNode->data = data;
                lastNode->next_node = (struct node *)curNode;
                plist->size++;
    
                printf("队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:%d
    ",plist->size);
                pthread_cond_signal(&(plist->cond_for_customer));
    
                // unlock
                pthread_mutex_unlock(&(plist->mutex));
                return ;
            }
            lastNode = curNode;
            curNode = (ListNode *)curNode->next_node;
        }
    }
    
    int block_queue_pop(List *plist,int *p_data) {
        // lock
        pthread_mutex_lock(&(plist->mutex));
        while(plist->size <= 0){
            printf("队列已空,消费者阻塞。目前仓储数量:%d
    ",plist->size);
            pthread_cond_wait(&(plist->cond_for_customer),&(plist->mutex));
        }
    
        ListNode *curNode = plist->firstNode;
        if(curNode == NULL){
            printf("队列为空,通知阻塞的生产者。目前仓储数量:%d
    ",plist->size);
            pthread_cond_signal(&(plist->cond_for_producer));
            // unlock
            pthread_mutex_unlock(&(plist->mutex));
            return 1;  // no data
        } else {
            *p_data = curNode->data;
            plist->firstNode = (ListNode *)curNode->next_node;
            free(curNode);
            plist->size--;
    
            printf("队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:%d
    ",plist->size);
            pthread_cond_signal(&(plist->cond_for_producer));
    
            // unlock
            pthread_mutex_unlock(&(plist->mutex));
            return 0;
        }
    }

    打印输出:

    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:1
    生产数据:0
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:2
    生产数据:0
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:1
    消费数据:0
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:2
    生产数据:1
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:3
    生产数据:1
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:2
    消费数据:0
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:3
    生产数据:2
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:4
    生产数据:2
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:3
    消费数据:1
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:4
    生产数据:3
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:5
    生产数据:3
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:4
    消费数据:1
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:5
    生产数据:4
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:6
    生产数据:4
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:5
    消费数据:2
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:6
    生产数据:5
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:7
    生产数据:5
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:6
    消费数据:2
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:7
    生产数据:6
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:8
    生产数据:6
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:7
    消费数据:3
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:8
    生产数据:7
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:9
    生产数据:7
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:8
    消费数据:3
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:9
    生产数据:8
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:8
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:4
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:9
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:4
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:5
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:9
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:5
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:6
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:11
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:6
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:12
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:7
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:11
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:7
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:12
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:8
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:13
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:8
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:14
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:9
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:13
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:10
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:14
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:9
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:15
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:10
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:16
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:11
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:15
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:12
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:16
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:11
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:17
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:12
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:18
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:13
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:17
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:14
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:18
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:13
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:19
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:14
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:20
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:15
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:19
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:16
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:20
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:15
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:21
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:16
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:22
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:17
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:23
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:18
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:24
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:17
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:21
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:18
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:22
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:19
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:25
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:20
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:26
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:19
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:23
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:20
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:24
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:21
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:27
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:22
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:28
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:23
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:25
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:24
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:26
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:21
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:29
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:22
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:30
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:25
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:27
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:26
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:28
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:23
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:31
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:24
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:32
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:27
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:29
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:28
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:30
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:25
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:33
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:26
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:34
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:29
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:31
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:30
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:32
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:27
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:35
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:28
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:36
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:31
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:33
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:32
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:34
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:29
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:35
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:30
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:36
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:33
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:37
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:34
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:38
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:31
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:37
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:32
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:38
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:35
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:10
    生产数据:39
    ---- 生产结束 ----
    队列已满,生产者阻塞。目前仓储数量:10
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:9
    消费数据:36
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:8
    消费数据:33
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:7
    消费数据:34
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:6
    消费数据:35
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:5
    消费数据:36
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:4
    消费数据:37
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:3
    消费数据:38
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:2
    消费数据:37
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:1
    消费数据:38
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:0
    消费数据:39
    队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量:1
    生产数据:39
    ---- 生产结束 ----
    队列被消费了一条数据,通知阻塞的生产者。目前仓储数量:0
    消费数据:39
    ---- 消费结束 ----

    例:实现线程的sleep函数。Linux是无法直接使线程sleep的,所以需要使用 pthread_cond_timedwait() 函数实现线程的sleep函数。

    以下实现性能可能有问题,因为需要重复初始化/销毁互斥量与等待条件量。这里主要是要给出pthread_cond_timedwait使用方法与简单实现sleep函数。

    main.c

    #include <stdio.h>
    #include <pthread.h>
    #include <time.h>
    #include "pthread_sleep.h"
    
    void test_loop();
    
    int main() {
        pthread_t thread;
        pthread_create(&thread,NULL,(void *)test_loop,NULL);
        pthread_join(thread,NULL);
        return 0;
    }
    
    void test_loop() {
        time_t now;
    
        for(;;){
            pthread_sleep(1);
            time(&now);
            printf("%s",asctime(gmtime(&now)));
        }
    }

    pthread_sleep.h

    #ifndef C_POINTER_PTHREAD_SLEEP_H
    #define C_POINTER_PTHREAD_SLEEP_H
    
    #endif //C_POINTER_PTHREAD_SLEEP_H
    
    unsigned int pthread_sleep(unsigned int seconds);

    pthread_sleep.c

    #include <pthread.h>
    #include <sys/time.h>
    #include "pthread_sleep.h"
    
    unsigned int pthread_sleep(unsigned int seconds) {
        pthread_cond_t cond;
        pthread_mutex_t mutex;
    
        // 创建锁
        pthread_cond_init(&cond,NULL);
        pthread_mutex_init(&mutex,NULL);
    
        // 时间计算。此处计算的是,等待的截止时间。即当前时刻到达这个时间点,线程就不再被阻塞。
        struct timeval now;
        gettimeofday(&now, NULL);
        struct timespec sleep_time = {now.tv_sec + seconds,0};
    
        // 加锁
        pthread_mutex_lock(&mutex);
    
        // 等待。等到到指定时间,继续执行。
        pthread_cond_timedwait(&cond,&mutex,&sleep_time);
    
        // 解锁
        pthread_mutex_unlock(&mutex);
    
        // 销毁
        pthread_cond_destroy(&cond);
        pthread_mutex_destroy(&mutex);
    
        return 0;
    }

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。

    http://www.cnblogs.com/shijiaqi1066/p/5769417.html

  • 相关阅读:
    【SCOI 2011】 糖果
    【POJ 3159】 Candies
    【POJ 1716】 Integer Intervals
    【POJ 2983】 Is the information reliable?
    【POJ 1364】 King
    【POJ 1201】 Intervals
    【POJ 1804】 Brainman
    6月10日省中提高组题解
    【POJ 3352】 Road Construction
    【POJ 1144】 Network
  • 原文地址:https://www.cnblogs.com/shijiaqi1066/p/5769417.html
Copyright © 2011-2022 走看看