用户级线程和内核级线程的区别以及用线程池实现生产者消费者模型

1.用户级线程

    什么是用户级线程?

    先看定义   关键点1.不需要内核支持

            2.在用户程序中实现线程调度

     那这么做的好处是什么呢?

    可以不用进行上下文(CONTEXT)切换。

    上下文就是程序的运行环境,包括变量的值,程序调用栈。在进行内核线程的切换时,会保存程序的上下文(就是程序的运行环境),处理器状态从用户态切换到内核态,这是一个很耗费资源的事情。而用户级线程的切换发生在用户级的应用程序空间,不用从用户态切换到内核态,只需要保存线程的运行状态就可以进行切换,提高了操作系统的执行效率。

  但是这种切换是发生在用户态的,操作系统内核无法得知,所以在操作系统看来这些用户级线程仅仅是一个进程,只会给他分配一个cpu,如果在单核的处理器上,这并没有什么大的关系。系统总共就一个CPU,但是在现代操作系统运行的硬件上一般都有多个cpu无法充分发挥多核CPU的优势。并且由于多个线程公用一个CPU,如果某个线程阻塞于某个系统调用上面的话,全部的线程都会阻塞。

2.内核级线程

    什么是内核级线程?内核级线程的特点与用户级线程相反,各个线程可以分配到多个CPU上面,但是进行线程调度的时候要进行上下文切换。

优点是充分发挥多处理器的优势,但是在进行线程调度时要进行上下文切换(其实这个在他的优点面前不算什么)

最后附上我今天写的线程池代码(基于linux下的pthread库--内核级线程)

main.c

#include "ThreadPool.h"
#include "unistd.h"
int main(void)
{
	ThreadPool threadpool(10,10);
	threadpool.init();
	while(true)
	{
      usleep(1000*1000);
	}
	return 0;
}

threadpool.cxx

#include "ThreadPool.h"
#include "stdlib.h"
#include "unistd.h" //usleep
//message type;
static std::string MessageType[5]={
   "我爱吃牛肉","我不吃牛肉",
   "我不吃牛肉","我不吃牛肉",
   "我不吃牛肉"
};
void* ThreadPool::ConsumerThread(void* threaddata)
{
  ThreadItem* curThread=static_cast<ThreadItem*>(threaddata);
  ThreadPool* pThreadPool=curThread->p_ThreadPool;
while(pThreadPool->isstop==false)
{
  while(pThreadPool->MessageCount==0)
  {
	//no message   sleep 500 ms
	usleep(500*1000);
	sem_wait(&pThreadPool->m_message_count);
    
  }
  //in this time,the number of count is not zero
  //so,you can go out of the loop.
  pthread_mutex_lock(&pThreadPool->MessageQueueMutex);
  pThreadPool->MessageCount--;
  std::string message=pThreadPool->MessageQueue.front();
  pThreadPool->MessageQueue.pop();

  std::cout<<message<<std::endl;
  sem_post(&pThreadPool->m_produce_count);
  //unlock
  pthread_mutex_unlock(&pThreadPool->MessageQueueMutex);
  //too tired   ,sleep  500 ms;
  usleep(500*1000);
}

  return (void*)0;
}

void* ThreadPool::ProduceThread(void* threaddata)
{
	int num=0;
	ThreadItem* curThread=static_cast<ThreadItem*>(threaddata);
    ThreadPool* pThreadPool=curThread->p_ThreadPool;
	//assume the capacity of message pool is 100;
	while(pThreadPool->isstop==false)
	{
	while(pThreadPool->MessageCount==100)
	{
		usleep(500*1000);
		sem_wait(&pThreadPool->m_produce_count);
		
        
	}
	pthread_mutex_lock(&pThreadPool->MessageQueueMutex);
    num=(num+1)%5;
	
    pThreadPool->MessageQueue.push(MessageType[num]);
	pThreadPool->MessageCount++;
	sem_post(&pThreadPool->m_message_count);
	pthread_mutex_unlock(&pThreadPool->MessageQueueMutex);
	}

  return (void*)0;

}

ThreadPool::ThreadPool(int consumerThreadNum,int producerThreadNum)
{
	sem_init(&m_message_count,0,0);
	sem_init(&m_produce_count,0,100);
	pthread_mutex_init(&MessageQueueMutex,NULL);
	MessageCount=0;
	this->consumerThreadNum=consumerThreadNum;
	this->producerThreadNum=producerThreadNum;
	
}
	  
ThreadPool::~ThreadPool()
{
  isstop=true;
  while(m_threads.size()!=0)
  {
	ThreadItem* p_thread=m_threads.back();
	m_threads.pop_back();
	pthread_join(p_thread->m_id,NULL);
	delete p_thread;
  }
  m_threads.clear();
  for(int i=0;i<MessageQueue.size();i++)
  {
	 
    
	std::string().swap(MessageQueue.front());
  }
  
    
}

bool ThreadPool::init()
{
    ThreadItem* thread;
    for(int i=0;i<consumerThreadNum;i++)
	{
		thread=new ThreadItem(this);
		m_threads.push_back(thread);
		pthread_create(&thread->m_id,NULL,ConsumerThread,thread);
	}
	for(int i=0;i<producerThreadNum;i++)
	{
		thread=new ThreadItem(this);
		m_threads.push_back(thread);
		pthread_create(&thread->m_id,NULL,ProduceThread,thread);
	}

}

threadpool.h

#include <pthread.h>
#include <string>
#include <iostream>
#include <queue>
#include <atomic>
#include<semaphore.h>
class ThreadPool
{
	//线程池内部类,定义传递给线程的信息  可以自己添加一些字段
	class ThreadItem
	{
		public:
		pthread_t m_id;
		ThreadPool* p_ThreadPool;
		ThreadItem(ThreadPool* p_this):p_ThreadPool(p_this)
		{};

	};
public:
      //线程池初始化
      ThreadPool(int consumerThreadNum,int producerThreadNum);
	  //释放资源
	  ~ThreadPool();
	  //生产者线程函数
	  static  void* ProduceThread(void* threaddata);
	  static  void* ConsumerThread(void* threaddata);
	  bool init();
private:
  //休息队列
  std::queue<std::string>  MessageQueue;
  //
  pthread_mutex_t    MessageQueueMutex;
  /// @brief C++11里的原子类型 操作过程不可被打断
  std::atomic<int>   MessageCount;
  sem_t              m_message_count;
  sem_t              m_produce_count;

  //线程记录队列
  std::vector<ThreadItem*>   m_threads;
  
  bool isstop=false;
  int consumerThreadNum;
  int producerThreadNum;
  
};

  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值