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。