#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h> typedef void* (*fun)(void*); fun fun1, fun2; pthread_mutex_t pmu = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond;
pthread_t pid1, pid2;
int flag = ;
int gnum = ;
int gsub = ; void * func1(void * para)
{
int k = (int)para;
printf("func1, ******\n");
while(gnum<=)
{
pthread_mutex_lock(&pmu);
printf("gnum == %d", gnum);
while(gnum==)
{
printf("suspend thread1 at gnum==50 !!! \n");
pthread_cond_wait(&cond, &pmu);
gnum++;
}
++gnum;
++flag;
++k;
//printf("flag = %d, k = %d\n", flag, k);
pthread_mutex_unlock(&pmu);
printf("I am func1\n");
}
pthread_exit((void*)); } void * func2(void * para)
{
int f = (int)para;
printf("f == %d\n", f);
printf("pthread2 start running !\n");
void * ret = NULL;
while(gsub>=)
{
pthread_mutex_lock(&pmu);
gsub--;
printf("gsub= %d ", gsub);
if(gsub == )
{
printf("now gsnb ==20, and send signal\n");
pthread_cond_signal(&cond);
}
++flag;
++f;
printf("flag = %d, f = %d\n", flag, f);
pthread_mutex_unlock(&pmu);
printf("I am func2 \n");
}
//pthread_join(pid1, &ret);
pthread_exit((void*));
} int main()
{
int id = ;
void * ret = NULL;
int key = ; pthread_cond_init(&cond, NULL); //属性设置NULL默认属性
id = pthread_create(&pid1, NULL, func1, (void*)key);
if(id != )
{
printf("pthread_create error !\n");
exit();
} if(pthread_create(&pid2, NULL, func2, (void*)key))
{
printf("pthread_create error ! \n");
exit();
}
87 pthread_join(pid2, &ret);      //等待pid2线程退出
88 pthread_join(pid1, &ret);      //等待pid1线程退出     //pthread_detach(pid1);        //主线程与pid1线程进行分离,一般用来实现异步返回
    //pthread_detach(pid2);        //同上
pthread_exit((void*));
}

gcc test_thread.c -lpthread
./a.out

线程池实例代码:

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h> typedef struct worker
{
//回调函数,任务运行时会调用此函数,也可以声明为其他形式;
void * (*process)(void *arg); //该函数返回值是任意类型的;参数也是任意类型的;`
void *arg; //回调函数的参数;
struct worker *next;
}CThread_worker; //线程池结构
typedef struct
{
pthread_mutex_t queue_lock; //互斥量
pthread_cond_t queue_ready; //条件变量 //链表结构, 线程池中所有等待任务
CThread_worker *queue_head; //是否销毁线程池
int shutdown;
pthread_t *threadid; //线程池中允许的活动线程数目;
//线程池中允许的活动线程数目;
int max_thread_num;
//当前等待队列的任务数目;
int cur_queue_size; }CThread_pool; int pool_add_worker(void * (*process)(void *arg), void *arg);
void * thread_routine(void *arg); static CThread_pool *pool = NULL;
void pool_init(int max_thread_num)
{
pool = (CThread_pool*)malloc(sizeof(CThread_pool)); //初始化互斥量;
pthread_mutex_init(&(pool->queue_lock), NULL);
//初始化条件变量
pthread_cond_init(&(pool->queue_ready), NULL); pool->queue_head = NULL; //最大线程数目
pool->max_thread_num = max_thread_num;
//当前线程数目
pool->cur_queue_size = ; pool->shutdown = ;
pool->threadid = (pthread_t*)malloc(max_thread_num * sizeof(pthread_t));
int i = ;
for(i=; i<max_thread_num;i++)
{
pthread_create(&(pool->threadid[i]), NULL, thread_routine, NULL);
}
} //向线程池中加入任务
int pool_add_worker(void*(*process)(void *arg), void *arg)
{
//构建一个新任务
CThread_worker *newworker = (CThread_worker *)malloc(sizeof(CThread_worker));
newworker->process = process;
newworker->arg = arg;
//别忘了置空
newworker->next = NULL; //加锁互斥量
pthread_mutex_lock(&(pool->queue_lock));
//将任务加入到等待队列中
CThread_worker *member = pool->queue_head;
if(member !=NULL)
{
while(member->next != NULL)
member = member->next;
member->next = newworker;
}
else
{
pool->queue_head = newworker;
} assert(pool->queue_head != NULL);
pool->cur_queue_size++;
pthread_mutex_unlock(&(pool->queue_lock)); //好了,等待队列中有任务了,唤醒一个等待线程;
// 注意如果所有线程都在忙碌,这句没有任何作用
pthread_cond_signal(&(pool->queue_ready));
return ;
} /*销毁线程池,等待队列中的任务不会再被执行,
*但是正在运行的线程会一直 把任务运行完后 再退出;
*/ int pool_destroy()
{
if(pool->shutdown)
return -; //防止两次调用
pool->shutdown = ; //唤醒所有等待线程,线程池要销毁了
pthread_cond_broadcast(&(pool->queue_ready)); //阻塞等待线程退出, 否则就成僵尸了
int i;
for(i=; i<pool->max_thread_num; i++)
{
pthread_join(pool->threadid[i], NULL);
} free(pool->threadid); //销毁等待队列
CThread_worker *head = NULL;
while(pool->queue_head != NULL)
{
head=pool->queue_head;
pool->queue_head = pool->queue_head->next;
free(head);
} //条件变量和互斥量也别忘了销毁
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready)); free(pool);
/*销毁后指针置空是个好习惯*/
pool = NULL;
return ;
} void* thread_routine(void *arg)
{
printf("start thread 0x%x\n", pthread_self());
while()
{
pthread_mutex_lock(&(pool->queue_lock));
/*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意
*pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
while(pool->cur_queue_size == && !pool->shutdown)
{
printf("thread 0x%x is waiting \n", pthread_self());
pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));
} //线程池要销毁了;
if(pool->shutdown)
{
//遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
pthread_mutex_unlock(&(pool->queue_lock));
printf("thread 0x %x will exit \n", pthread_self());
pthread_exit(NULL);
} printf("thread 0x %x is starting to work \n", pthread_self()); //使用断言
assert(pool->cur_queue_size!= );
assert(pool->queue_head!= NULL); //等待队列长度减去1,并取出链表中的头元素
pool->cur_queue_size--;
CThread_worker *worker = pool->queue_head;
pool->queue_head = worker->next;
pthread_mutex_unlock(&(pool->queue_lock)); //调用回调函数,执行任务
(*(worker->process))(worker->arg);
free(worker);
worker = NULL;
}
//这一句正常情况下是不可达的
pthread_exit(NULL);
} //test code
void *myprocess(void *arg)
{
printf("threadid is 0x%x, working on task %d\n", pthread_self(), *(int*)arg);
sleep(); //休息一秒,延长任务的执行时间
return NULL;
} int main(int argc, char** argv)
{
pool_init(); /*线程池中最多三个活动线程*/ //连续向线程池中放入10个任务;
int *workingnum = (int*)malloc(sizeof(int)*);
int i;
for(i=; i< ;i++)
{
workingnum[i] = i;
pool_add_worker(myprocess, &workingnum[i]);
} sleep();
//销毁线程池;
pool_destroy();
free(workingnum); return ;
}

linux多线程示例的更多相关文章

  1. 《Linux多线程服务端编程:使用muduo C++网络库》上市半年重印两次,总印数达到了9000册

    <Linux多线程服务端编程:使用muduo C++网络库>这本书自今年一月上市以来,半年之内已经重印两次(加上首印,一共是三次印刷),总印数达到了9000册,这在技术书里已经算是相当不错 ...

  2. Linux 多线程应用中如何编写安全的信号处理函数

    http://blog.163.com/he_junwei/blog/static/1979376462014021105242552/ http://www.ibm.com/developerwor ...

  3. LINUX多线程(一)(创建和退出)

    1. Linux多线程概述 1.1. 概述 进程是系统中程序执行和资源分配的基本单位.每个进程有自己的数据段.代码段和堆栈段.这就造成进程在进行切换等操作时都需要有比较负责的上下文切换等动作.为了进一 ...

  4. 笔记整理--Linux多线程

    Unix高级环境编程系列笔记 (2013/11/17 14:26:38) Unix高级环境编程系列笔记 出处信息 通过这篇文字,您将能够解答如下问题: 如何来标识一个线程? 如何创建一个新线程? 如何 ...

  5. Linux多线程编程初探

    Linux线程介绍 进程与线程 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程 ...

  6. Linux 多线程 - 线程异步与同步机制

    Linux 多线程 - 线程异步与同步机制 I. 同步机制 线程间的同步机制主要包括三个: 互斥锁:以排他的方式,防止共享资源被并发访问:互斥锁为二元变量, 状态为0-开锁.1-上锁;开锁必须由上锁的 ...

  7. ZT 为什么pthread_cond_t要和pthread_mutex_t同时使用 || pthread/Linux多线程编程

    为什么线程同步的时候pthread_cond_t要和pthread_mutex_t同时使用 (2009-10-27 11:07:23) 转载▼ 标签: 杂谈 分类: 计算机 举一个例子(http:// ...

  8. Linux 多线程应用中如何编写安全的信号处理函数【转】

    转自:https://www.cnblogs.com/virusolf/p/4945642.html http://blog.163.com/he_junwei/blog/static/1979376 ...

  9. Linux多线程服务器端编程

    目录 Linux多线程服务器端编程 线程安全的对象生命期管理 对象的销毁线程比较难 线程同步精要 借shared_ptr实现写时拷贝(copy-on-write) 多线程服务器的适用场合与常用编程模型 ...

随机推荐

  1. jni note

    2016-1-15 javah 使用javah可以自动从java文件生成jni头文件, 用法:javah [选项] <类> 其中 [选项] 包括:         -help        ...

  2. VIM+qmake编译示例程序HelloQt出错问题的解决(文件名一定要使用.cpp,否则就会默认使用gcc编译,当然通不过)

    之前看到很多初学Qt的Linux友们在使用qmake编译第一个HelloQt或者HelloWorld程序时报错,并且始终找不到原因. 前几天我也遇到了同样的问题,我用的是<精通Qt4编程> ...

  3. Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)

    Qt Windows下链接子系统与入口函数(终结版) 转载自:http://blog.csdn.net/dbzhang800/article/details/6358996 能力所限,本讨论仅局限于M ...

  4. shell 学习笔记1501-1800

    .巧用bash的{}扩展备份目录: cp file.txt{,.bak} .利用at执行一次性命令: echo "ls -l" | at midnight #Execute a c ...

  5. uva 12171 hdu 1771 Sculpture

    //这题从十一点开始写了四十分钟 然后查错一小时+ 要吐了 这题题意是给很多矩形的左下角(x,y,z最小的那个角)和三边的长(不是x,y,z最大的那个角T-T),为组成图形的面积与表面积(包在内部的之 ...

  6. 使用sphinx索引mysql数据

    数据库表如下 mysql> select * from tb_account; +----+-------+------+ | id | name | age | +----+-------+- ...

  7. SQL语句一些特殊的用法

    SQL语句一些特殊的用法 一.基础 1.说明:创建数据库 CREATE DATABASE database-name  2.说明:删除数据库 drop database dbname 3.说明:备份s ...

  8. mockjax MOCK.js的拦截ajax请求

    今天看了下 mock.js的拦截请求 .https://github.com/nuysoft/Mock/blob/master/src/mockjax.js //覆盖(拦截) Ajax 请求,目前内置 ...

  9. JavaScript奇技淫巧45招

    JavaScript奇技淫巧45招 撰写于 2015年1月5日 修改于 2016年6月16日 分类 翻译 标签 JavaScript 本文是一篇翻译文章,原文信息如下: 原文:45 Useful Ja ...

  10. Samba在CentOS下的图形化界面的安装

    第一步:构建yum仓库(在此用的是北交大的yum仓库) 打开目录/etc/yum.repos.d下的CentOS-Base.repo文件,此处是我自己建的yum仓库,修改里面的链接地址为北交大的镜像的 ...