Thread Class
进程与线程
进程(英语:process),是指计算机中已运行的程序。进程曾经是分时系统的基本运作单位。
线程(英语:thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
以上摘自Wiki
\(std::thread定义于头文件 <thread>\)
构造函数
#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
void f1(int n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 1 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
void f2(int& n)
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 2 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
class foo
{
public:
void bar()
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 3 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
class baz
{
public:
void operator()()
{
for (int i = 0; i < 5; ++i) {
std::cout << "Thread 4 executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
baz b;
std::thread t1; // t1 不是线程
std::thread t2(f1, n + 1); // 按值传递
std::thread t3(f2, std::ref(n)); // 按引用传递
std::thread t4(std::move(t3)); // t4 现在运行 f2() 。 t3 不再是线程
std::thread t5(&foo::bar, &f); // t5 在对象 f 上运行 foo::bar()
std::thread t6(std::ref(b)); // t6 在对象 b 上运行 baz::operator()
std::thread t7([]{std::cout << "Thread 4 executing\n" << std::endl;})// 通过Lambda表达式创建
t2.join();
t4.join();
t5.join();
t6.join();
std::cout << "Final value of n is " << n << '\n';
std::cout << "Final value of foo::n is " << f.n << '\n';
std::cout << "Final value of baz::n is " << b.n << '\n';
}
/*
Thread 1 executing
Thread 2 executing
Thread 3 executing
Thread 4 executing
Thread 3 executing
Thread 1 executing
Thread 2 executing
Thread 4 executing
Thread 2 executing
Thread 3 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 2 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 1 executing
Thread 2 executing
Thread 4 executing
Final value of n is 5
Final value of foo::n is 5
Final value of baz::n is 5
*/
以上摘自cppreference
成员类id
get_id() 返回线程的id。
#include <iostream>
#include <thread>
using namespace std;
int main()
{
thread t1([] {cout << "线程创建成功!" << endl;});
cout << "线程id为:" << t1.get_id() << endl;
t1.join();
return 0;
}
/*
线程id为:2
线程创建成功!
*/
成员函数
join
阻塞当前进程,直至join所指进程执行完毕,也就是只有等join里面的进程执行结束后才能执行join后面的语句
未加join阻塞线程
#include <iostream>
#include <thread>
using namespace std;
void func()
{
for (int i = 1; i <= 5; ++ i)
cout << i << endl;
}
int main()
{
thread t1(func);
for (int i = 1; i <= 100000; ++ i);
for (int i = 1; i <= 5; ++ i)
cout << "永远嘀神!" << endl;
t1.join();
return 0;
}
/*
永远嘀神!
永远嘀神!
1永远嘀神!
永远嘀神!2
永远嘀神!3
4
5
*/
由运行结果可看出func(子线程)和main(主线程)同时运行
加了join之后
#include <iostream>
#include <thread>
using namespace std;
void func()
{
for (int i = 1; i <= 5; ++ i)
cout << i << endl;
}
int main()
{
thread t1(func);
t1.join();
for (int i = 1; i <= 100000; ++ i);
for (int i = 1; i <= 5; ++ i)
cout << "永远嘀神!" << endl;
return 0;
}
/*
1
2
3
4
5
永远嘀神!
永远嘀神!
永远嘀神!
永远嘀神!
永远嘀神!
*/
主线程等待子线程执行完再执行
再看一个例子
#include <iostream>
#include <thread>
using namespace std;
void func()
{
using one_second = chrono::duration<double, ratio<1,1>>;
this_thread::sleep_for(one_second(3));
cout << "线程创建成功" << endl;
}
int main()
{
thread t1(func);
cout << "永远嘀神!" << endl;
return 0;
}
/*
永远嘀神!
terminate called without an active exception
*/
子线程在主线程结束是被强制终止。
detach
被detach后的线程成为守护线程或者分离线程,该线程脱离主线程的管制,成为独立的一个线程,运行完后由操作系统回收
#include <iostream>
#include <thread>
using namespace std;
void func()
{
// using one_second = chrono::duration<double, ratio<1,1>>;
// //this_thread::sleep_for(one_second(0.5));
cout << "线程创建成功" << endl;
}
int main()
{
thread t1(func);
t1.detach();
cout << "永远嘀神!" << endl;
return 0;
}
/*
永远嘀神!
*/
joinable
判断线程是否结束
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
std::thread t;
std::cout << "before starting, joinable: " << std::boolalpha << t.joinable()
<< '\n';
t = std::thread(foo);
std::cout << "after starting, joinable: " << t.joinable()
<< '\n';
t.join();
std::cout << "after joining, joinable: " << t.joinable()
<< '\n';
}
/*
before starting, joinable: false
after starting, joinable: true
after joining, joinable: false
*/
swap
交换两个thread的内容
#include <iostream>
#include <thread>
#include <chrono>
void foo()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
void bar()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
}
int main()
{
using std::swap;
std::thread t1(foo);
std::thread t2(bar);
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
std::cout << "thread 1 address: " << &t1 << std::endl;
std::cout << "thread 2 address: " << &t2 << std::endl;
swap(t1, t2);
std::cout << "after std::swap(t1, t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
std::cout << "thread 1 address: " << &t1 << std::endl;
std::cout << "thread 2 address: " << &t2 << std::endl;
swap(t1, t2);
std::cout << "after t1.swap(t2):" << std::endl;
std::cout << "thread 1 id: " << t1.get_id() << std::endl;
std::cout << "thread 2 id: " << t2.get_id() << std::endl;
std::cout << "thread 1 address: " << &t1 << std::endl;
std::cout << "thread 2 address: " << &t2 << std::endl;
t1.join();
t2.join();
}
/*
thread 1 id: 2
thread 2 id: 3
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
after std::swap(t1, t2):
thread 1 id: 3
thread 2 id: 2
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
after t1.swap(t2):
thread 1 id: 2
thread 2 id: 3
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
*/