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

  • 相关阅读:
    (转)JQuery中$.ajax()方法参数详解
    __dopostback的用法 . 编辑
    (转)__dopostback的用法 .
    (转)如何区分一个程序员是“老手“还是“新手“?
    jQuery验证框架 .
    location.href的用法
    为用户设置密码
    设置环境变量
    用 xampp 在ubuntu 下配置php 运行环境 lampp
    安装与配置JDK
  • 原文地址:https://www.cnblogs.com/shijiaqi1066/p/5769417.html
Copyright © 2011-2022 走看看