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;
};