一.线程最主要的三个同步机制

1.信号量

2.互斥锁

3.条件变量

二.对三个同步机制分别实现一个包装类#ifdef LOCKER_H

#define LOCKER_H

#include #include /*信号量的封装*/

class sem

{

public:

sem()

{

if( sem_init( &sem_like, 0, 0))

{

throw std::exception();

}

}

~sem()

{

sem_destroy( &sem_like);

}

bool wait()

{

return sem_wait( &sem_like)== 0;

}

bool post()

{

return sem_post( &sem_like)== 0;

}

private:

sem_t sem_like;

}

/*互斥锁的封装*/

class locker

{

public:

locker()

{

if( pthread_mutex_init( &mutex_like,NULL) !=0)

{

throw std::exception();

}

}

~locker()

{

pthread_mutex_destroy( &mutex_like);

}

bool lock()

{

return pthread_mutex_lock( &mutex_like)== 0;

}

bool unlock()

{

return pthread_mutex_unlock( &mutex_like);

}

private:

pthread_mutex_t mutex_like;

}

/*条件变量的封装*/

class cond

{

public:

cond()

{

if( pthread_mutex_init( &mutex_like,NULL)!= 0)

{

throw std::exception;

}

if( pthread_cond_init( &cond_like, NULL)!= 0)

{

//释放对应的互斥锁

pthread_mutex_destroy( &mutex_like);

throw std::exception;

}

}

~cond()

{

pthread_mutex_destroy( &mutex_like);

pthread_cond_destroy( &cond_like);

}

bool wait()

{

int flag= 0;

pthread_mutex_lock( &mutex_like);

flag= pthread_cond_wait( &cond_like, &mutex_like);

pthread_mutex_unlock( &mutex_like);

return flag== 0;

}

bool signal()

{

return pthread_cond_signal( &cond_like)== 0;

}

private:

pthread_mutex_t mutex_like;

pthread_cond_t cond_like;

}

#endif

三.实现线程池

动态创建线程十分消耗时间,如果有一个线程池,用户请求到来时,从线程池取一个空闲的线程来处理用户的请求,请求处理完后,线程又变为空闲状态,等待下次被使用。

核心数据结构有两个:线程容器 、请求队列

1.线程容器

这里用一个vector容器来存放线程池里面所有线程的id

2.请求队列

这里用list容器来存放所有请求,请求处理按fifo的顺序

#ifndef THREADPOOL_H

#define THREADPOOL_H

#include #include #include #include #include "locker.h"

template< typename T >

class threadpool

{

public:

threadpool( int thread_number = 8, int max_requests = 10000 );

~threadpool();

bool append( T* request );

private:

static void* worker( void* arg );

void run();

private:

int thread_number_like;//当前线程池中的线程个数

int max_requests_like;//最大请求数

//pthread_t* threads_like;

vector< pthread> threads_like;//线程容器

std::list< T* > workqueue_like;//请求队列

locker queuelocker_like;//请求队列的访问互斥锁

sem queuestat_like;//用于请求队列与空闲线程同步的信号量

bool stop_like;//结束所有线程,线程池此时没有线程

};

template< typename T >

threadpool< T >::threadpool( int thread_number, int max_requests ) :

m_thread_number( thread_number ), m_max_requests( max_requests ), m_stop( false ), m_threads( NULL )

{

if( ( thread_number <= 0 ) || ( max_requests <= 0 ) )

{

throw std::exception();

}

threads_like.resize( thread_number_like);

if( thread_number_like!= threads_like.size() )

{

throw std::exception();

}

for ( int i = 0; i < thread_number_like; ++i )

{

printf( "create the %dth thread\n", i );

if( pthread_create( &threads_like [i], NULL, worker, this ) != 0 )//创建线程

{

threads_like.resize(0);

throw std::exception();

}

if( pthread_detach( m_threads[i] ) )//设置为脱离线程

{

threads_like.resize(0);

throw std::exception();

}

}

}

template< typename T >

threadpool< T >::~threadpool()

{

stop_like = true;

}

template< typename T >

bool threadpool< T >::append( T* request )

{

queuelocker_like.lock();

if ( workqueue_like.size() > max_requests_like )

{

queuelocker_like.unlock();

return false;

}

workqueue_like.push_back( request );

queuelocker_like.unlock();

queuestat_like.post();

return true;

}

template< typename T >

void* threadpool< T >::worker( void* arg )

{

threadpool* pool = ( threadpool* )arg;//静态函数要调用动态成员run,必须通过参数arg得到

pool->run();//线程的执行体

return pool;

}

template< typename T >

void threadpool< T >::run()

{

while ( ! m_stop )

{

queuestat_like.wait();

queuelocker_like.lock();

if ( workqueue_like.empty() )

{

queuelocker_like.unlock();

continue;

}

T* request = workqueue_like.front();

workqueue_like.pop_front();

queuelocker_like.unlock();

if ( ! request )

{

continue;

}

request->process();//执行当前请求所对应的处理函数

}

}

#endif

注:1.这里的线程池模型中,每一个线程对应一个请求

2.这种方式保证了用户请求的及时处理,对请求的处理函数性能要求更小,因为这种模型并不要求请求处理过程是非堵塞的,因为一个请求的处理时延不会影响到系统对其他请求的处理(当然线程数必须能动态增加)。

3.这种方式对于高并发服务器并不是最优的,类似于nginx的一个进程对应多个用户请求的方式更有优势,nginx模型的优势主要有两个:一:进程数固定,不会因为同时有很多线程或者进程而占用过多的内存。二:nginx的工作进程数一般与cpu的核数一致,并可以把一个进程绑定到一个核上,这样就节省了进程切换或线程切换带来的系统开销

以上就介绍了实现一个线程池,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

php每一个请求会创建一个线程吗,实现一个线程池相关推荐

  1. 操作系统:为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?Tomcat服务器工作原理?

    为什么IO操作不占用CPU却会导致进程阻塞?Web服务器每接收一个请求都会创建一个新的线程吗?这两个问题在我学操作系统以前我都挺困惑的.现在我来尝试着解答一下. 1. 为什么IO操作不占用CPU却会导 ...

  2. Jmeter TCP 取样器 上一个请求响应结果参数传个下一个请求,响应结果为空

    出现的问题,上一个请求成功,但是下一个请求返回参数是200 ,但是响应结果为空,如图.原因是因为我没有勾选close connection 每个请求结束后关闭连接. 先来了解一下TCP 取样器界面的的 ...

  3. 新建Android项目,会出现两个项目一个是自己创建的项目,另一个是“appcompat_v7”项目,这是怎么回事呢?该怎么解决呢?...

    做Android开发的朋友最近会发现,更新ADT至22.6.0版本之后,创建新的安装项目,会出现appcompat_v7的内容.并且是创建一个新的内容就会出现.这到底是怎么回事呢?原来appcompa ...

  4. 什么是进程?什么是线程?进程与线程的区别?

    目录 什么是进程?什么是线程? 为什么要有线程? 进程与线程的区别? 进程与线程的选择取决条件? 什么是进程?什么是线程? 进程:进程是并发执行程序在执行过程中资源分配和管理的基本单位(资源分配的最小 ...

  5. 一个请求方法是一个线程吗?不是!

    首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的.各 ...

  6. C语言socket accept()函数(提取出所监听套接字的等待连接队列中第一个连接请求,创建一个新的套接字,并返回指向该套接字的文件描述符)

    文章目录 名称 使用格式 功能参数描述 参数 sockfd addr addrlen 返回值 示例 man 2 文档中的accept解释 错误处理 名称 accept() 接收一个套接字中已建立的连接 ...

  7. java 一个线程运行_Java并发(基础知识)—— 创建、运行以及停止一个线程

    在计算机世界,当人们谈到并发时,它的意思是一系列的任务在计算机中同时执行.如果计算机有多个处理器或者多核处理器,那么这个同时性是真实发生的:如果计算机只有一个核心处理器那么就只是表面现象. 现代所有的 ...

  8. 一个http请求就是一个线程吗,java的服务是每收到一个请求就新开一个线程来处理吗...

    一个http请求就是一个线程吗,java的服务是每收到一个请求就新开一个线程来处理吗 答案是:是,一个http请求,就是一个线程. https://blog.csdn.net/elvis_lfc/ar ...

  9. 一个进程可以创建多少线程?

    理论上,一个进程可用虚拟空间是2G,默认情况下,线程的栈的大小是1MB,所以理论上一个进程可以创建2048个线程,当然更改编译器的设置可以创建多余2048个线程 因此,一个进程可以创建的线程数由可用虚 ...

最新文章

  1. 全球及中国汽车紧急呼叫终端行业运营模式及未来投资方向建议报告2022版
  2. 军规22 充分使用持续集成和持续部署
  3. python settings模块安装_Python settings-helper包_程序模块 - PyPI - Python中文网
  4. python日志输出 超量 停止_linux 内存分配参数导致的 buffer_pool 分配不出来的问题排查...
  5. http服务器响应格式,熟悉Http协议的请求和响应格式,编写一个简单的Http服务器。 基本要求:1 正确解...
  6. vs2015+opencv3.2.0配置的一些小事情
  7. ASoC Codec驱动代码框架图
  8. 软件工程师与码农的区别
  9. ARM寄存器的操作方法
  10. 真鱼游来游去动态壁纸_真鱼动态壁纸
  11. TimesTen Classic 18c 卸载 (uninstall)全过程
  12. 华胜天成-容灾流程管理平台解决方案
  13. word设置实验报告格式
  14. 为什么哲学是最难的学科_世界十大哲学难题:全球哲学家都苦恼的哲学问题盘点...
  15. 10-Redis 笔记
  16. android webview 本地视频播放,Android中webview html5 自动播放本地视频
  17. h5调用指纹识别_H5 画布指纹识别
  18. 【BI学习心得04-ALS算法与推荐系统】
  19. unity shader 入门 全透明与半透明效果实现
  20. 【机器学习】李宏毅 - 02 回归

热门文章

  1. 前端布局之一html、css
  2. 中国石油大学《软件工程》机考题
  3. Super PI linux 版本最新可用
  4. java.sql.SQLException: Incorrect string value: '\xF0\x9F\x90\x9B],...' for column 'DESCR' at row 1问题
  5. narwal无法连接机器人_地宝DJ35连不上网/连网失败/无法连接APP
  6. Velocity开发指南-内容
  7. 超好用的纯C语言矩阵运算库
  8. 粉色卡通小学班干部竞选自我介绍PPT模板
  9. IDEA隐藏target目录
  10. Android自定义多TAB悬浮控件实现蘑菇街首页效果