与传统进程相比,用线程来实现相同的功能有如下优点:
(1)系统资源消耗低。
(2)速度快。
(3)线程间的数据共享比进程间容易的多。
二、多线程编程简单实例#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <pthread.h>voidthread1_routine(void){ PRintf("new thread:thread_id is %u, process_id is %u/n", pthread_self(), getpid());}voidthread2_routine(void){ printf("new thread:thread_id is %u, process_id is %u/n", pthread_self(), getpid());}intmain(void){ pthread_t pt; printf("old thread:thread_id is %u, process_id is %u/n", pthread_self(), getpid()); pthread_create(&pt, NULL, (void *)thread1_routine, NULL); pthread_create(&pt, NULL, (void *)thread2_routine, NULL); usleep(5); return(0);}
运行结果如下(可以看出在同一个进程中有三个不同的线程同时在运行):
三、线程属性线程属性包括绑定属性、分离属性、堆栈地址、堆栈大小和优先级。其中分离属性、堆栈地址以及堆栈大小的介绍可参考http://www.CUOXin.com/nufangrensheng/p/3522583.html。系统默认的是非邦定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。在pthread_create中,把第二个参数设置为NULL的话,将采用默认的属性配置。
1、绑定属性
线程可以分为用户级线程和内核级线程两种(可参考http://blog.csdn.net/songjinshi/article/details/9042265以及http://www.xuebuyuan.com/1380720.html),而绑定属性正是设置用户级线程和内核级线程之间的关系。
绑定属性分为两种:绑定和非绑定。在绑定属性下,一个用户级线程固定分配给一个内核线程,因为CPU时间片的调度是面向内核线程(轻量级进程)的,因此具有 绑定属性的线程可以保证在需要的时候总有一个内核线程与之对应。在非绑定属性下,用户线程和内核线程的关系不是始终固定的,而是由系统根据实际情况分配的。
2、优先级
四、线程互斥生产者消费者实例(多线程+互斥量):
#include <stdio.h>#include <pthread.h>#include <sched.h>void *producter_f(void *arg);void *consumer_f(void *arg);int buffer_has_item = 0;pthread_mutex_t mutex;int running = 1;int main(void){ pthread_t consumer_t; pthread_t producter_t; pthread_mutex_init(&mutex, NULL); pthread_create(&producter_t, NULL, (void *)producter_f, NULL); pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL); sleep(1); /* 等待线程创建完毕 */ running = 0; pthread_join(consumer_t, NULL); pthread_join(producter_t, NULL); pthread_mutex_destroy(&mutex); return(0);}void *producter_f(void *arg){ while(running) { if(buffer_has_item < 10) /* 最多允许生产10个 */ { pthread_mutex_lock(&mutex); buffer_has_item++; printf("product, total: %d/n", buffer_has_item); pthread_mutex_unlock(&mutex); } }}void *consumer_f(void *arg){ while(running) { if(buffer_has_item > 0) /* 缓冲区为空时不允许再消费 */ { pthread_mutex_lock(&mutex); buffer_has_item--; printf("consume, total: %d/n", buffer_has_item); pthread_mutex_unlock(&mutex); } }}
编译运行结果如下:
五、线程中使用信号量
(此处使用的信号量是POSIX无名信号量:http://www.CUOXin.com/nufangrensheng/p/3564306.html)
线程的信号量与进程的信号量类似,使用线程的信号量可以高效地完成基于线程的资源计数。信号量实际上是一个非负的整数计数器,用来实现对公共资源的控制。在公共资源增加的时候,信号量的值增加;公共资源消耗的时候,信号量的值减少;只有当信号量的值大于0时,才能允许访问信号量所代表的公共资源。
生产者消费者实例(多线程+信号量):
#include <stdio.h>#include <pthread.h>#include <semaphore.h>void *producter_f(void *arg);void *consumer_f(void *arg);sem_t sem;int running = 1;int main(void){ pthread_t consumer_t; pthread_t producter_t; sem_init(&sem, 0, 16); pthread_create(&producter_t, NULL, (void *)producter_f, NULL); pthread_create(&consumer_t, NULL, (void *)consumer_f, NULL); sleep(1); running = 0; pthread_join(consumer_t, NULL); pthread_join(producter_t, NULL); sem_destroy(&sem); return(0);}void *producter_f(void *arg){ int semval = 0; while(running) { usleep(1); sem_post(&sem); sem_getvalue(&sem, &semval); printf("product, total: %d/n", semval); }}void *consumer_f(void *arg){ int semval = 0; while(running) { usleep(1); sem_wait(&sem); sem_getvalue(&sem, &semval); printf("consume, total: %d/n", semval); }}编译运行如下:
更多关于线程的介绍可参考http://www.CUOXin.com/nufangrensheng/p/3518114.html及其后续博文。
新闻热点
疑难解答