c++多线程基础一
1、线程的启动结束和创建线程
1.1 thread 创建
c++ 11之前的linux创建方法:
pthread_create 创建线程, pthread_create使用
三种创建方法:
-
用一个初始函数创建一个线程
#include <iostream> #include <thread> using namespace std; void print1() { cout << "print1_1线程执行" << endl; cout << "print1_2线程执行" << endl; cout << "print1_3线程执行" << endl; } int main() { thread mythread1(print1); mythread1.join(); cout << "主线程执行" << endl; return 0; } -
用类对象创建一个线程
#include <iostream> #include <thread> using namespace std; class T { public: void operator()() { cout << "print2_1线程执行" << endl; cout << "print2_2线程执行" << endl; cout << "print2_3线程执行" << endl; } }; int main() { T t; thread mythread2(t); mythread2.join(); cout << "主线程执行" << endl; return 0; } -
用lambda表达式创建一个线程
#include <iostream> #include<thread> using namespace std; int main() { //用lambda表达式创建一个线程 auto mylamthread = [] {//这是一个lambda表达式 cout << "我的线程开始执行了" << endl; //...... cout << "我的线程执行结束了" << endl; }; thread mythread3(mylamthread); mythread3.join(); cout << "主线程执行结束" << endl; return 0;//表示主线程执行结束,表明进程结束 }
同时,使用thread变量,再连接线程执行函数:
std::thread t;
t = std::thread(fun);
1.2 join方法
join()函数是一个等待线程完成函数,主线程需要等待子线程运行结束了才可以结束
注意:这里相当于主线程在这里等待子线程结束运行,才执行之后的命令
1.3 detach方法
detach()函数是子线程的分离函数,当调用该函数后,线程就被分离到后台运行,主线程不需要等待该线程结束才结束;称为守护线程或者分析线程。
linux 启动程序变为后台进程,可以使用在最后加入&即可;
注意:detach 线程后注意子线程和主线程中变量的关系,防止引用或者指针主线程释放的场景,导致子线程异常。
- 传递临时对象作为线程参数
- 传递临时变量作为线程参数
- 传递类对象或者只能指针作为宪政参数
- 使用成员函数指针作为线程参数
1.4 joinable方法
用于判断程序是否可以使用detach或者join方法,同时也是为了防止多次调用join导致异常,如果已经join,则返回false
1.5 获取线程ID
-
调用pthread_create 返回值即为线程id
#include <pthread.h> pthread_t tid; tid = pthread_create(&tid, NULL, thread_proc, NULL); -
pthread_self 函数获取
#include <pthread.h> pthread_t tid = pthread_self(); tid = pthread_create(&tid, NULL, thread_proc, NULL); -
syscall调用系统获取
#include <sys/syscall.h> #include <unistd.h> int tid = syscall(SYS_gettid); -
get_id 调用
#include <thread> std::thread::id id = std::this_thread::get_id();
2 如何确保创建的线程一定能够运行
使用条件变量通知:
#include <thread>
#include <mutex>
#include <condition_variable>
#include <iostream>
std::mutex mymutex;
std::condition_variable mycv;
bool success = false;
void thread_func()
{
{
std::unique_lock<std::mutex> lock(mymutex);
success = true;
mycv.notify_all();
}
while(true) {
}
}
int main()
{
std::thread t(thread_func);
// 使用{} 减小锁的粒度
{
std::unique_lock<std::mutex> lock(mymutex);
while(!success) {
mycv.wait(lock);
}
}
std::cout<< "start thread successfully." << std::endl;
t.join();
return 0;
}
3 线程局部变量
3.1 linux 线程局部变量
linux 上的NTPL 提供了一套函数接口来实现线程局部存储功能:
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*));
int pthread_key_delete(pthread_key_t* key);
int pthread_setspecific(pthread_key_t* key, const void* value);
void* pthread_getspecific(pthread_key_t* key);
示例:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_key_t thread_log_key;
void write_to_thread_log(const char* message)
{
if (message == NULL) {
return;
}
FILE* logfile = (FILE*) pthread_getspecific(thread_log_key);
fprintf(logfile, "%s\n", message);
fflush(logfile);
}
void close_thread_log(void* logfile)
{
char logfilename[128];
sprintf(logfilename, "close logfile: thread%ld.log\n", (unsigned long)pthread_self());
printf("%s\n", logfilename);
fclose((FILE*)logfile);
}
void* thread_function(void* args)
{
char logfilename[128];
sprintf(logfilename, "thread%ld.log", (unsigned long)pthread_self());
FILE* logfile = fopen(logfilename, "w");
if (logfile != NULL) {
pthread_setspecific(thread_log_key, logfile);
write_to_thread_log("Thread starting ...");
}
return NULL;
}
int main()
{
pthread_t threadIDs[5];
pthread_key_create(&thread_log_key, close_thread_log);
for(int i = 0; i < 5; i++) {
pthread_create(&threadIDs[i], NULL, thread_function, NULL);
}
for(int i = 0; i < 5; i++) {
pthread_join(threadIDs[i], NULL);
}
return 0;
}
编译:
gcc -g -o linux_local_thread linux_local_thread.cpp -lpthread
运行:
lhh@DESKTOP-KDO04Q4:/mnt/d/project_code/c++Server$ ./linux_local_thread
close logfile: thread140045352830720.log
close logfile: thread140045361284864.log
close logfile: thread140045369739008.log
close logfile: thread140045344376576.log
close logfile: thread140045378193152.log
4 线程池实例
4.1 类设计
thread_pool.h
class ThreadPool
{
public:
ThreadPool(int thread_count):
thread_count_(thread_count)
{
}
~ThreadPool();
bool Init();
void Submit(std::function<void ()> task);
void Shutdown();
private:
void ThreadWorker();
void Wait();
int thread_count_;
std::mutex mutex_;
std::mutex cv_mutex_;
std::condition_variable cv_;
bool shutdown_ = false;
std::queue<std::function<void ()>> pending_tasks_;
std::vector<std::thread> threads_;
};
4.2 thread_pool实现细节
thread_pool.c
ThreadPool::~ThreadPool()
{
}
bool ThreadPool::Init()
{
for (int i = 0; i < thread_count_; ++i) {
threads_.push_back(std::move(std::thread(std::bind(&ThreadPool::ThreadWorker, this))));
}
return true;
}
void ThreadPool::ThreadWorker()
{
while (!shutdown_) {
while (!pending_tasks_.empty()) {
std::function<void ()> task;
{
std::lock_guard<std::mutex> lock(mutex_);
if (!pending_tasks_.empty()) {
task = pending_tasks_.front();
pending_tasks_.pop();
}
}
if (task) {
task();
}
}
Wait();
}
}
void ThreadPool::Submit(std::function<void ()> task)
{
{
std::lock_guard<std::mutex> lock(mutex_);
pending_tasks_.push(task);
}
cv_.notify_all();
}
void ThreadPool::Wait()
{
std::unique_lock<std::mutex> lk(cv_mutex_);
cv_.wait_until(lk, std::chrono::steady_clock::now() + std::chrono::seconds(1));
}
void ThreadPool::Shutdown()
{
shutdown_ = true;
for (auto& thread: threads_) {
thread.join();
}
}
浙公网安备 33010602011771号