日期:2014-05-16 浏览次数:20643 次
这个是比较简单的例子,有助于初学多线程的人理解多线程的工作模式,后期会不断的跟进多线程的进阶应用等。
储备知识:
1.多线程是一种多任务并发的工作方式,在linux中线程包括内核线程和用户线程,内核线程有内核管理,不需要我们做更多的工作,我们这里将的是用户线程,线程统一由用户线程来切换。
2.线程相关函数:
int pthread_create(pthread_t id,pthread_attr_t *attr, void *(*start_runtine)(void *), void *arg);//线程创建函数
获取线程ID(即上面创建的pthread_t id):pthread_t pthread_self();
退出线程:void pthread_exit(void *retval);
挂起线程:int pthread_join(pthread_t id,void **return);
线程同步:在POSIX中提供线程同步的方式有两种,条件变量和互斥锁
互斥锁:
pthread_mutex_t *mutex;//互斥锁变量
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_attr_t *attr);//初始化一个互斥锁
int pthread_mutex_lock(pthread_mutex_t *mutex);//锁定互斥锁,这样子当一个线程锁定的话,另一个线程就会处于等待状态
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁互斥锁,如果解锁后,处于等待状态的线程就有机会访问临界区
条件变量:其实是对互斥锁的一种补充,因为线程可以在等待条件变量的时候同时解锁,这在生产者和消费者模式可以体现。
pthread_cond_t cond;
int pthread_cond_init(pthread_cond_t *cond, const pthread_cond_addr *attr);//初始化一个条件变量,后面参数attr是条件变量的属性
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);//释放互斥量mutex,等待条件变量cond
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime);//释放互斥量mutex,等待条件变量cond,与pthread_cond_wait函数不一样的是,该函数可以是线程在abstime时间内不阻塞。
int pthread_cond_signal(pthread_cond_t *cond);//释放条件变量
int pthread_cond_broadcast(pthread_cond_t *cond);//释放所有由cond阻塞的线程,这里要小心使用
3.线程属性,这些属性在使用前,必须调用相关的初始化函数pthread_xxx_init(xxx *);
线程属性:pthread_attr_t
typedef struct { int detachstate; 线程的分离状态,这个跟pthread_join相关,如果一个线程调用join获取另一个线程的状态的时候,就需要用到这个属性。 int schedpolicy; 线程调度策略 struct sched_param schedparam; 线程的调度参数 int inheritsched; 线程的继承性 int scope; 线程的作用域 size_t guardsize; 线程栈末尾的警戒缓冲区大小 int stackaddr_set; void * stackaddr; 线程栈的位置 size_t stacksize; 线程栈的大小 }pthread_attr_t;上面的相关属性,POSIX大部分都提供了相应的接口来操作。如设置调度测略:int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);等
int pthread_attr_init(pthread_attr_t *attr);//初始化线程属性对象
int pthread_attr_destroy(pthread_attr_t *attr);//销毁线程属性对象
。。。。。
例子:10个窗口协作卖掉150张票
下面是正常情况下,150张票依次由窗口0~9号卖完,即0号卖完10张票,接下来1号继续卖完十张票。。。这种是常规的处理方法,代码实现如下:
#define NUMOFTICKET 150 #define NUMAGENT 10 void sellTickets(int agent, int task); int main() { int i; for(i = 0; i < NUMAGENT; i++) { sellTickets(i,NUMOFTICKET/NUMAGENT); } return 0; } void sellTickets(int agent, int task) { assert(agent >= 0); while(task > 0) { printf("agent %d sell one ticket!\n",agent); task--; } printf("agent %d sell all ticket!\n",agent); }但是这种方式比较不符合现代的服务方式,现在一般都是0~9号窗口同时卖票,哪个窗口有空闲时间,有多余的票数就可以提供服务,这种用多线程的方法就可以实现这种方法:
static int numofticket = 150; const int numofagent = 10; pthread_mutex_t mutex; void* sellTicket(void* agent); int main() { int i; int fail = -1;
pthread_t npid[numofagent] for(i = 0;i<numofagent; i++) { fail = -1; fail = pthread_create(&npid[i],NULL, sellTicket,(int *)i);//创建10个线程,10个线程调用sellTicket函数 if(!fail) { printf("Create thread %d success!\n",i); } &nbs