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.\n");
        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.\n");
    }
    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!\n");
        return -1;
    }

    /*创建线程二*/
    ret=pthread_create(&id_2, NULL, (void  *) thread_2, NULL);
    if(ret != 0) {
        printf("Create pthread error!\n");
        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\n",rc1);
    }

    // 创建线程
    int rc2 = pthread_create(&thread2, NULL, (void *)add_1, &i);
    if(rc2 != 0){
        printf("thread-2 create failed: %d\n",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\n",i);
    }

    printf("---- 生产结束 ----\n");
    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\n",data);
    }

    printf("---- 消费结束 ----\n");
    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\n",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\n",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\n",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\n",plist->size);
        pthread_cond_wait(&(plist->cond_for_customer),&(plist->mutex));
    }

    ListNode *curNode = plist->firstNode;
    if(curNode == NULL){
        printf("队列为空,通知阻塞的生产者。目前仓储数量:%d\n",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\n",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

posted @ 2016-08-14 02:33  LaplaceDemon  阅读(3287)  评论(0编辑  收藏  举报