线程池C语言版本源码(Daniel Robbins著,注释及修正归个人)
来源:互联网 发布:全自动风水罗盘软件 编辑:程序博客网 时间:2024/05/21 17:24
queue.h---------------------------------------------------------------------
typedef struct node {
struct node *next;
} node;
struct node *next;
} node;
typedef struct queue {
node *head, *tail;
} queue;
node *head, *tail;
} queue;
void queue_init(queue *myroot);
void queue_put(queue *myroot, node *mynode);
node *queue_get(queue *myroot);
queue.c---------------------------------------------------------------------
void queue_put(queue *myroot, node *mynode);
node *queue_get(queue *myroot);
queue.c---------------------------------------------------------------------
#include <stdio.h>
#include "queue.h"
#include "queue.h"
void queue_init(queue *myroot) {
myroot->head=NULL;
myroot->tail=NULL;
}
myroot->head=NULL;
myroot->tail=NULL;
}
void queue_put(queue *myroot,node *mynode) {
mynode->next=NULL;
if (myroot->tail!=NULL)
myroot->tail->next=mynode;
myroot->tail=mynode;
if (myroot->head==NULL)
myroot->head=mynode;
}
mynode->next=NULL;
if (myroot->tail!=NULL)
myroot->tail->next=mynode;
myroot->tail=mynode;
if (myroot->head==NULL)
myroot->head=mynode;
}
node *queue_get(queue *myroot) {
//get from root
node *mynode;
mynode=myroot->head;
if (myroot->head!=NULL)
myroot->head=myroot->head->next;
return mynode;
}
debug.h---------------------------------------------------------------------
//get from root
node *mynode;
mynode=myroot->head;
if (myroot->head!=NULL)
myroot->head=myroot->head->next;
return mynode;
}
debug.h---------------------------------------------------------------------
#define dabort() /
{ printf("Aborting at line %d in source file %s/n",__LINE__,__FILE__); abort(); }
{ printf("Aborting at line %d in source file %s/n",__LINE__,__FILE__); abort(); }
control.h-------------------------------------------------------------------
#include <pthread.h>
typedef struct data_control {
pthread_mutex_t mutex;
pthread_cond_t cond;
int active;
} data_control;
control.c-------------------------------------------------------------------
pthread_mutex_t mutex;
pthread_cond_t cond;
int active;
} data_control;
control.c-------------------------------------------------------------------
#include "control.h"
int control_init(data_control *mycontrol) {
int mystatus;
if (pthread_mutex_init(&(mycontrol->mutex),NULL))
return 1;
if (pthread_cond_init(&(mycontrol->cond),NULL))
return 1;
mycontrol->active=0;
return 0;
}
int mystatus;
if (pthread_mutex_init(&(mycontrol->mutex),NULL))
return 1;
if (pthread_cond_init(&(mycontrol->cond),NULL))
return 1;
mycontrol->active=0;
return 0;
}
int control_destroy(data_control *mycontrol) {
int mystatus;
if (pthread_mutex_destroy(&(mycontrol->mutex)))
return 1;
if (pthread_cond_destroy(&(mycontrol->cond)))
return 1;
mycontrol->active=0;
return 0;
}
int control_activate(data_control *mycontrol) {
int mystatus;
if (pthread_mutex_lock(&(mycontrol->mutex)))
return 0;
mycontrol->active=1;
pthread_mutex_unlock(&(mycontrol->mutex));
pthread_cond_broadcast(&(mycontrol->cond));
return 1;
}
int mystatus;
if (pthread_mutex_destroy(&(mycontrol->mutex)))
return 1;
if (pthread_cond_destroy(&(mycontrol->cond)))
return 1;
mycontrol->active=0;
return 0;
}
int control_activate(data_control *mycontrol) {
int mystatus;
if (pthread_mutex_lock(&(mycontrol->mutex)))
return 0;
mycontrol->active=1;
pthread_mutex_unlock(&(mycontrol->mutex));
pthread_cond_broadcast(&(mycontrol->cond));
return 1;
}
int control_deactivate(data_control *mycontrol) {
int mystatus;
if (pthread_mutex_lock(&(mycontrol->mutex)))
return 0;
mycontrol->active=0;
pthread_mutex_unlock(&(mycontrol->mutex));
pthread_cond_broadcast(&(mycontrol->cond));
return 1;
}
workcrew.c------------------------------------------------------------------
int mystatus;
if (pthread_mutex_lock(&(mycontrol->mutex)))
return 0;
mycontrol->active=0;
pthread_mutex_unlock(&(mycontrol->mutex));
pthread_cond_broadcast(&(mycontrol->cond));
return 1;
}
workcrew.c------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "control.h"
#include "queue.h"
#include "dbug.h"
#include <stdlib.h>
#include "control.h"
#include "queue.h"
#include "dbug.h"
#define NUM_WORKERS 24
int numthreads;
/*工作序列提供需要多个线程完成的工作任务 */
struct work_queue {
data_control control;//多线程控制结构体实例
queue work;//工作序列
} wq;//带有控制结构的任务序列
data_control control;//多线程控制结构体实例
queue work;//工作序列
} wq;//带有控制结构的任务序列
/* 这里为每个工作任务增加了一个资源值
通常一个工作节点都会有需要处理的额外数据
可以理解为参数,多个可使用结构体完成*/
typedef struct work_node {
struct node *next;
int jobnum;
} wnode;
struct node *next;
int jobnum;
} wnode;
/* 清扫线程处理已停下的线程,线程结束
之前,它将把自己添加进这个链表,因为
主线程一直在监视这个列表中的变化,然后
采取适当的动作如唤醒或释放新的中止线程
*/
之前,它将把自己添加进这个链表,因为
主线程一直在监视这个列表中的变化,然后
采取适当的动作如唤醒或释放新的中止线程
*/
struct cleanup_queue {
data_control control;
queue cleanup;
} cq;
data_control control;
queue cleanup;
} cq;
/* I added a thread number (for debugging/instructional purposes) and
a thread id to the cleanup node. The cleanup node gets passed to
the new thread on startup, and just before the thread stops, it
attaches the cleanup node to the cleanup queue. The main thread
monitors the cleanup queue and is the one that performs the
necessary cleanup. */
a thread id to the cleanup node. The cleanup node gets passed to
the new thread on startup, and just before the thread stops, it
attaches the cleanup node to the cleanup queue. The main thread
monitors the cleanup queue and is the one that performs the
necessary cleanup. */
typedef struct cleanup_node {
struct node *next;
int threadnum;
pthread_t tid;
} cnode;
struct node *next;
int threadnum;
pthread_t tid;
} cnode;
void *threadfunc(void *myarg) {
fflush(stdin);
printf("I AM THREADFUNC /n");
wnode *mywork;
cnode *mynode;
mynode=(cnode *) myarg;//线程节点被作为参数传了进来
pthread_mutex_lock(&wq.control.mutex);
printf("before while while wq.control.active = %d in thread %d /n",wq.control.active,mynode->threadnum);
fflush(stdout);
while (wq.control.active)
{//第一次时为1
while (wq.work.head==NULL && wq.control.active)
{//虽然任务控制结构状态处于解锁状态,
//但没有任务节点
printf(" pthread_cond_wait in thread %d/n",mynode->threadnum);
pthread_cond_wait(&wq.control.cond, &wq.control.mutex);
}
printf(" pthread_cond_not_wait in thread %d/n",mynode->threadnum);
printf("before break wq.control.active = %d in thread %d /n",wq.control.active,mynode->threadnum);
if (!wq.control.active) //如果任务控制处于锁定状态
break;//跳出while(wq.control.active)
//任务控制结构状态处于解锁状态,任务序列头结点不空
mywork=(wnode *) queue_get(&wq.work);//接任务单
pthread_mutex_unlock(&wq.control.mutex);//解锁任务控制结构,其他线程可修改
//只是打印消息,没有处理函数
printf("Thread number %d processing job %d/n",mynode->threadnum,mywork->jobnum);
free(mywork);//释放任务节点内存
pthread_mutex_lock(&wq.control.mutex);//在pthread_cond_wait之前一定要加锁
}
{//第一次时为1
while (wq.work.head==NULL && wq.control.active)
{//虽然任务控制结构状态处于解锁状态,
//但没有任务节点
printf(" pthread_cond_wait in thread %d/n",mynode->threadnum);
pthread_cond_wait(&wq.control.cond, &wq.control.mutex);
}
printf(" pthread_cond_not_wait in thread %d/n",mynode->threadnum);
printf("before break wq.control.active = %d in thread %d /n",wq.control.active,mynode->threadnum);
if (!wq.control.active) //如果任务控制处于锁定状态
break;//跳出while(wq.control.active)
//任务控制结构状态处于解锁状态,任务序列头结点不空
mywork=(wnode *) queue_get(&wq.work);//接任务单
pthread_mutex_unlock(&wq.control.mutex);//解锁任务控制结构,其他线程可修改
//只是打印消息,没有处理函数
printf("Thread number %d processing job %d/n",mynode->threadnum,mywork->jobnum);
free(mywork);//释放任务节点内存
pthread_mutex_lock(&wq.control.mutex);//在pthread_cond_wait之前一定要加锁
}
/*总结:
1. 多线程状态变量和互斥锁的函数调用次序不可颠倒:
A: pthread_mutex_lock -->B: pthread_cond_wait --> C: pthread_mutex_unlock
2. 任务完成以后一定要及时释放任务所占用的内存资源
3. 线程自身的收尾合并工作也需要特别注意,可以使用
状态变量信号相同的方法,也可以使用可分离状态
*/
printf(" not in while while in thread %d/n",mynode->threadnum);
1. 多线程状态变量和互斥锁的函数调用次序不可颠倒:
A: pthread_mutex_lock -->B: pthread_cond_wait --> C: pthread_mutex_unlock
2. 任务完成以后一定要及时释放任务所占用的内存资源
3. 线程自身的收尾合并工作也需要特别注意,可以使用
状态变量信号相同的方法,也可以使用可分离状态
*/
printf(" not in while while in thread %d/n",mynode->threadnum);
pthread_mutex_unlock(&wq.control.mutex);
pthread_mutex_lock(&cq.control.mutex);
queue_put(&cq.cleanup,(node *) mynode);
pthread_mutex_unlock(&cq.control.mutex);
pthread_cond_signal(&cq.control.cond);
printf("thread %d shutting down.../n",mynode->threadnum);
return NULL;
}
queue_put(&cq.cleanup,(node *) mynode);
pthread_mutex_unlock(&cq.control.mutex);
pthread_cond_signal(&cq.control.cond);
printf("thread %d shutting down.../n",mynode->threadnum);
return NULL;
}
void join_threads(void) {
cnode *curnode;
cnode *curnode;
printf("joining threads.../n");
while (numthreads) {
//注意wait函数的调用次序 先锁后等再解
pthread_mutex_lock(&cq.control.mutex);
//注意wait函数的调用次序 先锁后等再解
pthread_mutex_lock(&cq.control.mutex);
/* 下面的代码睡眠以等待一个新的清除节点
用于清除一个线程,这一点需要格外小心
尤其被错误的唤醒,即便我们从函数pthread/-cond/-wait
中醒来,我们也不应该想当然的认为我们等待
的状态就真的到来了
*/
while (cq.cleanup.head==NULL) {
pthread_cond_wait(&cq.control.cond,&cq.control.mutex);
}
/* 条件真的到来时,我们控制住互斥锁并且
线程队列里面有我们要处理的线程对象首
先我们将该节点从线程队列里删除然后通
过存储在线程节点的tid 调用pthread_join 来合并
该线程,只有等到这个函数返回时才能认为
该线程已经停止才能调用释放内存函数free()
来删除节点占用的内存资源,减少需要处理
线程个数,如果需要就循环该段代码
*/
用于清除一个线程,这一点需要格外小心
尤其被错误的唤醒,即便我们从函数pthread/-cond/-wait
中醒来,我们也不应该想当然的认为我们等待
的状态就真的到来了
*/
while (cq.cleanup.head==NULL) {
pthread_cond_wait(&cq.control.cond,&cq.control.mutex);
}
/* 条件真的到来时,我们控制住互斥锁并且
线程队列里面有我们要处理的线程对象首
先我们将该节点从线程队列里删除然后通
过存储在线程节点的tid 调用pthread_join 来合并
该线程,只有等到这个函数返回时才能认为
该线程已经停止才能调用释放内存函数free()
来删除节点占用的内存资源,减少需要处理
线程个数,如果需要就循环该段代码
*/
curnode = (cnode *) queue_get(&cq.cleanup);//取头结点
pthread_mutex_unlock(&cq.control.mutex);//解锁
pthread_join(curnode->tid,NULL);//合并线程
printf("joined with thread %d/n",curnode->threadnum);//已经合并
//释放内存
free(curnode);
numthreads--;//待合并线程个数自减一次
}
}
pthread_mutex_unlock(&cq.control.mutex);//解锁
pthread_join(curnode->tid,NULL);//合并线程
printf("joined with thread %d/n",curnode->threadnum);//已经合并
//释放内存
free(curnode);
numthreads--;//待合并线程个数自减一次
}
}
int create_threads(void) {
int x;
cnode *curnode;
for (x=0; x<NUM_WORKERS; x++) {
curnode=malloc(sizeof(cnode));
if (!curnode)
return 1;
curnode->threadnum=x;
printf("creat thread %d/n",x);
if (pthread_create(&curnode->tid, NULL, threadfunc, (void *) curnode))
return 1;
numthreads++;//全局变量表示线程池中的线程总数
}
return 0;
}
curnode=malloc(sizeof(cnode));
if (!curnode)
return 1;
curnode->threadnum=x;
printf("creat thread %d/n",x);
if (pthread_create(&curnode->tid, NULL, threadfunc, (void *) curnode))
return 1;
numthreads++;//全局变量表示线程池中的线程总数
}
return 0;
}
void initialize_structs(void) {
numthreads=0;
if (control_init(&wq.control))//wq.control.active=0
dabort();
queue_init(&wq.work);//头尾置为NULL
if (control_init(&cq.control)) {//cq.contol.active=0
control_destroy(&wq.control);
dabort();
}
queue_init(&cq.cleanup); //头尾置为NULL
control_activate(&wq.control);//wq.control.active=1
}
numthreads=0;
if (control_init(&wq.control))//wq.control.active=0
dabort();
queue_init(&wq.work);//头尾置为NULL
if (control_init(&cq.control)) {//cq.contol.active=0
control_destroy(&wq.control);
dabort();
}
queue_init(&cq.cleanup); //头尾置为NULL
control_activate(&wq.control);//wq.control.active=1
}
void cleanup_structs(void) {
printf("CAN THR CLEANUP_STRUCT BE EXETED HERE /n");
control_destroy(&cq.control);
control_destroy(&wq.control);
}
control_destroy(&cq.control);
control_destroy(&wq.control);
}
int main(void) {
int x;
wnode *mywork;
wnode *mywork;
initialize_structs();
//初始化完成后阶段性成果为工作,线程池队列都
//初始化头尾置为NULL 且将wq.control.active=1 cq.con.act=0
/* 创建线程 */
if (create_threads()) {
printf("Error starting threads... cleaning up./n");
join_threads();
dabort();
}
printf("this is main thread,numthreads=%d/n",numthreads);
//锁定工作任务队列添加工作项
pthread_mutex_lock(&wq.control.mutex);
printf("wq.control.active=%d in main 215/n",wq.control.active);
printf("lock wq.control.mutex in main/n");
for (x=0; x<16; x++) {
mywork=malloc(sizeof(wnode));
if (!mywork) {
printf("ouch! can't malloc!/n");
break;
}
mywork->jobnum=x;
queue_put(&wq.work,(node *) mywork);
}
//添加完成后解锁并广播工作任务序列已修改
printf("unlock wq.control.mutex in main/n");
pthread_mutex_unlock(&wq.control.mutex);
printf("broadcast wq.control.cond in main/n");
pthread_cond_broadcast(&wq.control.cond);
//等待线程池里的线程把任务一扫而空
printf("sleeping.../n");
sleep(2);
//初始化完成后阶段性成果为工作,线程池队列都
//初始化头尾置为NULL 且将wq.control.active=1 cq.con.act=0
/* 创建线程 */
if (create_threads()) {
printf("Error starting threads... cleaning up./n");
join_threads();
dabort();
}
printf("this is main thread,numthreads=%d/n",numthreads);
//锁定工作任务队列添加工作项
pthread_mutex_lock(&wq.control.mutex);
printf("wq.control.active=%d in main 215/n",wq.control.active);
printf("lock wq.control.mutex in main/n");
for (x=0; x<16; x++) {
mywork=malloc(sizeof(wnode));
if (!mywork) {
printf("ouch! can't malloc!/n");
break;
}
mywork->jobnum=x;
queue_put(&wq.work,(node *) mywork);
}
//添加完成后解锁并广播工作任务序列已修改
printf("unlock wq.control.mutex in main/n");
pthread_mutex_unlock(&wq.control.mutex);
printf("broadcast wq.control.cond in main/n");
pthread_cond_broadcast(&wq.control.cond);
//等待线程池里的线程把任务一扫而空
printf("sleeping.../n");
sleep(2);
printf("wq.control.active=%d in main 235/n",wq.control.active);
//感觉差不多执行完了以后将工作任务序列由激活变为非激活
printf("deactivating work queue.../n");
control_deactivate(&wq.control);//wq.control.active=0
/* 完成对所有线程组成的线程队列的清理工作*/
printf("wq.control.active=%d in main 240/n",wq.control.active);
join_threads();//合并回收所有线程
cleanup_structs();//释放所有已分配的内存资源防止内存泄漏
//感觉差不多执行完了以后将工作任务序列由激活变为非激活
printf("deactivating work queue.../n");
control_deactivate(&wq.control);//wq.control.active=0
/* 完成对所有线程组成的线程队列的清理工作*/
printf("wq.control.active=%d in main 240/n",wq.control.active);
join_threads();//合并回收所有线程
cleanup_structs();//释放所有已分配的内存资源防止内存泄漏
printf("this is last line before return 0/n");
return 0;
/*
主函数总结:
1. 主函数本身可以作为管理线程
2. 管理线程的执行流程是
A :初始化工作任务和线程队列-->B:创建线程组并置为听等态
--->C:向工作任务组里添加任务激活工作组并广播让线程工作
----->D:休眠等待线程们把工作做完---->E:锁定工作组改变
激活状态并监听合并线程状态信号(此时线程们监听到工作组
激活状态改变信号后跳出傻乎乎的为工作疲于奔命状态开始
发信号广播要求休息合并---->F:主线程收到线程组们的抗议信号
return 0;
/*
主函数总结:
1. 主函数本身可以作为管理线程
2. 管理线程的执行流程是
A :初始化工作任务和线程队列-->B:创建线程组并置为听等态
--->C:向工作任务组里添加任务激活工作组并广播让线程工作
----->D:休眠等待线程们把工作做完---->E:锁定工作组改变
激活状态并监听合并线程状态信号(此时线程们监听到工作组
激活状态改变信号后跳出傻乎乎的为工作疲于奔命状态开始
发信号广播要求休息合并---->F:主线程收到线程组们的抗议信号
后及时合并线程,防止线程上访,然后做善后事宜,回收内存。
*/
}
*/
}
- 线程池C语言版本源码(Daniel Robbins著,注释及修正归个人)
- POSIX 线程详解(1) by Daniel Robbins
- Daniel Robbins sed 实例 POSIX 线程详解
- POSIX线程详解(Daniel Robbins, 总裁兼 CEO, Gentoo Technologies, Inc.)
- 通用线程:POSIX 线程详解------------作者——Daniel Robbins
- 线程池我修正的源码 MFC
- 线程池我修正的源码 MFC
- Linux线程池(C语言)及简单实现示例
- (个人开源)nginx源码注释
- 完整详尽的二叉排序树性质及源码和注释 C语言 可直接运行
- 注释c语言源码(输入M和N,从M行注释到N行)
- 线程池原理及C语言实现线程池
- word2vec源码解析(注释合理版本)
- nginx注释版本源码
- 注释转换(c语言注释转为c++注释)
- 注释转换(c语言注释转为c++注释)
- 并归排序 c语言数据结构
- C语言做的接鸡蛋小游戏(附源码注释)【原创】
- uC/OS-II 简介
- 什么是MMU
- 考研还是就业?
- 今日项目咋设置成全屏呢?
- 如何防止私有方法被反射调用?
- 线程池C语言版本源码(Daniel Robbins著,注释及修正归个人)
- i++和i--哪个效率高?
- 浅谈嵌入式Linux驱动程序开发要点
- 字符驱动程序实例剖析
- ASP.NET程序中常用的三十三种代码 (一)
- ASP.NET程序中常用的三十三种代码 (二)
- ASP.NET程序中常用的三十三种代码 (三)
- CRASH
- ASP.NET程序中常用的三十三种代码 (四)