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 = ;
for(i = ; i <= ; i++) {
printf("This is a pthread_1.\n");
if(i == ) {
pthread_exit();
}
sleep();
}
} // 线程二
void thread_2(void) {
int i;
for(i = ; i < ; i++) {
printf("This is a pthread_2.\n");
}
pthread_exit();
} int main(void) {
pthread_t id_1, id_2;
int ret; /*创建线程一*/
ret=pthread_create(&id_1, NULL, (void *) thread_1, NULL);
if(ret != ) {
printf("Create pthread error!\n");
return -;
} /*创建线程二*/
ret=pthread_create(&id_2, NULL, (void *) thread_2, NULL);
if(ret != ) {
printf("Create pthread error!\n");
return -;
} /*等待线程结束*/
pthread_join(id_1, NULL);
pthread_join(id_2, NULL);
return ;
}
线程执行函数的返回值
- 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 != ){
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 = ; // 声明线程
pthread_t thread1,thread2; // 初始化锁
pthread_mutex_init(&mutex,NULL); // 创建线程
int rc1 = pthread_create(&thread1, NULL, (void *)add_1, &i);
if(rc1 != ){
printf("thread-1 create failed: %d\n",rc1);
} // 创建线程
int rc2 = pthread_create(&thread2, NULL, (void *)add_1, &i);
if(rc2 != ){
printf("thread-2 create failed: %d\n",rc1);
} // 等待线程
pthread_join(thread1,NULL);
pthread_join(thread2,NULL); printf("i = %d",i); // 打印输出 i = 210 return ;
} // 线程运行函数
void add_1(void *arg){
int *i = (int *)arg;
for(int n=;n<;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!=){
puts("生产者线程创建失败");
return EXIT_FAILURE;
} pthread_ret = pthread_create(&producer_thread_1,NULL,(void *)producer,plist);
if(pthread_ret!=){
puts("生产者线程创建失败");
return EXIT_FAILURE;
} pthread_ret = pthread_create(&customer_thread,NULL,(void *)customer,plist);
if(pthread_ret!=){
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 = ; i < ; 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 = ; i < ; 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 = ;
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 = ;
int ret = ; // 销毁所有数据。
while(ret==){
if(plist->size > ) {
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 <= ){
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 ; // 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 ;
}
}
打印输出:
队列刚才生产一条数据,通知阻塞的消费者。目前仓储数量: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 ;
} void test_loop() {
time_t now; for(;;){
pthread_sleep();
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,}; // 加锁
pthread_mutex_lock(&mutex); // 等待。等到到指定时间,继续执行。
pthread_cond_timedwait(&cond,&mutex,&sleep_time); // 解锁
pthread_mutex_unlock(&mutex); // 销毁
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex); return ;
}
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/5769417.html
Linux C —— 多线程的更多相关文章
- [转]Linux 的多线程编程的高效开发经验
Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多线程 API 有一些细微和隐晦的差别.不注意这些 Linux 上的一些开发陷阱,常常会导致程序问题不穷,死锁不断.本文中我们 ...
- 转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)
Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可 ...
- Linux 的多线程编程的高效开发经验(转)
http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...
- Linux 的多线程编程的高效开发经验
http://www.ibm.com/developerworks/cn/linux/l-cn-mthreadps/ 背景 Linux 平台上的多线程程序开发相对应其他平台(比如 Windows)的多 ...
- Linux C 多线程
原文:Linux C 多线程 linux下C语言多线程编程 #include <pthread.h> #include <stdio.h> #include <sys/t ...
- Linux下多线程编程遇到的一些问题
今天在学习了Linux的多线程编程的基础的知识点.于是就试着做了一个简单的Demo.本以为会得到预期的结果.不成想却遇到了意想不到的问题. 代码展示 我的C 代码很简单,就是一个简单的示例程序,如下: ...
- [转载]解决linux 下多线程错误 undefined reference to `sem_init'
转自:https://blog.csdn.net/yzycqu/article/details/7396498?utm_source=copy 解决linux 下多线程错误 undefined ref ...
- linux C 多线程/线程池编程 同步实例
在多线程.线程池编程中经常会遇到同步的问题. 1.创建线程 函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, ...
- Linux内核多线程实现方法 —— kthread_create函数【转】
转自:http://blog.csdn.net/sharecode/article/details/40076951 Linux内核多线程实现方法 —— kthread_create函数 内核经常需要 ...
- Linux中多线程信号的处理
1. 博文:Linux多线程中使用信号-1 http://blog.csdn.net/qq276592716/article/details/7325250 2. 博文:Linux多线程信号总结 ...
随机推荐
- BZOJ_1612_[Usaco2008_Jan]_Cow_Contest_奶牛的比赛_(dfs)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1612 \(n\)头奶牛比赛,给出一些胜负情况,问可以确定多少头奶牛的排名. 分析 无论胜负,只 ...
- Linux kernel AACRAID Driver Compat IOCTL 本地安全绕过漏洞
漏洞名称: Linux kernel AACRAID Driver Compat IOCTL 本地安全绕过漏洞 CNNVD编号: CNNVD-201311-390 发布时间: 2013-11-29 更 ...
- 物联网操作系统HelloX V1.77(beta)版本发布
物联网操作系统HelloX V1.77发布 经过近半年的努力,物联网操作系统HelloX V1.77版本正式完成,源代码已上载到github(github.com/hellox-project/Hel ...
- noip 2014 子矩阵
先枚举行再DP列.好题,详见代码 #include <cstdio> #include <cstring> #include <cstdlib> #include ...
- Esper系列(九)NamedWindow语法create、Insert、select
功能:用于存储一种或多种类型的事件的集合,并能对所存储的事件进行增删改查操作. CreateNameWindow 根据已有的数据源构造 格式: 1 [context context_name] 2 ...
- 8-14-Exercise(博弈:HDU 1846 & HDU 1527 )
B.HDU 1846 Brave Game 算是最简单的入门博弈题吧...... 呃......我用的......算是不是方法的方法吧——找规律~ 可以发现:X-M为奇数时,先手会输:而为偶数的 ...
- weapon制作武器
weapon制作武器 (weapon.pas/c/cpp) 解题报告 制作武器weapon.pas/c/cpp) 背景 WZland的紧急避难所很快就建好了,WZland的居民们陆续地来到这个紧急避难 ...
- elasticsearch的基本用法
开始学习使用 elasticsearch, 把步骤记录在这里: 最大的特点: 1. 数据库的 database, 就是 index 2. 数据库的 table, 就是 tag 3. 不要使用bro ...
- Python 学习入门(28)—— 服务器实例
在新的Python 3.x中,BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer整合到http.server包,SocketServer改名为sockets ...
- $.post()请求 ation请求,jsp获取的处理结果
public void write(String content, String charset) { getHttpResponse().setCharacterEncoding(charset); ...