阅读量:1
文章目录
九、多线程
3. C++11中的多线程
Linux中是根据多线程库来实现多线程的,C++11也有自己的多线程,那它的多线程又是怎样的?我们来使用一些C++11的多线程。
Makefile:
testThread: testThread.cc g++ -o $@ $^ -std=c++11 .PHONY: clean clean: rm -f testThread
testThread.cc
#include <iostream> #include <thread> #include <unistd.h> using namespace std; void threadrun(int num) { while (num) { cout << "I am thread, num : " << num << endl; sleep(1); --num; } } int main() { thread t1(threadrun, 10); while (true) { cout << "I am main thread" << endl; sleep(1); } t1.join(); return 0; }
编译看看:
我们发现有问题(也可能是其他问题),这是怎么回事呢?其实是 C++11的多线程本质上是对原生线程的封装。所以同样需要链接 phread 动态库。
Makefile:
testThread: testThread.cc g++ -o $@ $^ -std=c++11 -lpthread .PHONY: clean clean: rm -f testThread
我们再试试:
确实大部分其编程语言的多线程都是对原生线程的封装,原因是为了可移植性。
我们在进程部分学过 非阻塞等待 ,进程在等待子进程退出时,可以执行其他任务,在线程这里,同样有这样的技术,叫做线程分离。我们要是不关注线程的结果,只需要线程把自己的任务完成,这种情况就可以将线程进行分离。
Makefile:
testThread: testThread.cc g++ -o $@ $^ -std=c++11 -lpthread .PHONY: clean clean: rm -f testThread
testThread.cc:
#include <iostream> #include <pthread.h> #include <string> #include <unistd.h> using namespace std; void* threadrun(void* args) { string str = (const char*)args; int cnt = 5; while (true) { if (!(cnt--)) break; cout << "I am a new thread " << endl; sleep(1); } } int main() { pthread_t tid; pthread_create(&tid, nullptr, threadrun, (void*)"thread1"); // 线程分离 pthread_detach(tid); while (true) { cout << "I am the main thread " << endl; sleep(1); } return 0; }
默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。
joinable和分离是冲突的,一个线程不能既是joinable又是分离的。如果将线程分离了又对其join,就会出错。
线程分离底层依旧是属于进程,没有分开,线程分离只是一种状态,唯一的区别就是主线程不需要等待新线程。
4. 线程的简单封装
Makefile:
testThread: testThread.cc g++ -o $@ $^ -std=c++11 -lpthread .PHONY: clean clean: rm -f testThread
Thread.hpp:
#ifndef __THREAD_HPP__ #define __THREAD_HPP__ #include <iostream> #include <pthread.h> #include <string> #include <functional> #include <unistd.h> // 线程命名空间 namespace ThreadModule { // 线程函数模板 template<typename T> using func_t = std::function<void(T&)>; // 线程模板 template<typename T> class Thread { public: Thread(func_t<T> func, T data, const std::string& name = "none-name") :_func(func) ,_data(data) ,_threadname(name) ,_stop(true) {} void Excute() { _func(_data); } static void* threadtoutine(void* args) { Thread<T>* self = (Thread<T>*)args; self->Excute(); return nullptr; } // 启动线程 bool Start() { int n = pthread_create(&_tid, nullptr, threadtoutine, this); if (n == 0) { _stop = false; return true; } else return false; } // 分离线程 void Detach() { if (!_stop) { pthread_detach(_tid); } } // 等待线程结束 void Join() { if (!_stop) { pthread_join(_tid, nullptr); } } std::string name() { return _threadname; } // 停止线程 void Stop() { _stop = true; } ~Thread(){} private: pthread_t _tid; std::string _threadname; T _data; func_t<T> _func; bool _stop; }; } #endif
testThread.cc:
#include <iostream> #include <vector> #include "Thread.hpp" using namespace ThreadModule; const int num = 10; // 线程执行的任务 void print(int& cnt) { while (cnt) { std::cout << "hello I am myself thread, cnt: " << cnt-- << std::endl; sleep(1); } } int main() { // 创建多线程 std::vector<Thread<int>> threads; // 创建num个线程,每个线程执行print函数 for (int i = 0; i < num; ++i) { std::string name = "thread-" + std::to_string(i + 1); threads.emplace_back(print, 10, name); } // 启动线程 for (auto& thread : threads) { thread.Start(); } // 等待线程结束 for (auto& thread : threads) { thread.Join(); std::cout << "wait thread done, thread name: " << thread.name() << std::endl; } return 0; }
结果: