参考:
https://blog.csdn.net/qq_44891434/article/details/132559929
https://www.cnblogs.com/chen-cs/p/13055211.html
#include
std::thread t(function_name, args...);
function_name是线程入口点的函数或可调用对象
args…是传递给函数的参数,当调用的函数是无参的可以空着。
创建线程后,我们可以使用t.join()等待线程完成,join()函数的作用是让主线程的等待该子线程完成,然后主线程再继续执行
或者使用t.detach()分离线程,让它在后台运行。
一个子线程只能调用join()和detach()中的一个,且只允许调用一次。
使用**++ -std=c++11 -o thread thread.cpp -lpthread**编译
#include
#include
void print_message(const std::string& message) {
std::cout << message << std::endl;
}
void increment(int& x) {
++x;
}
int main() {
std::string message = "Hello, world!";
std::thread t(print_message, message);
t.join();
int x = 0;
std::thread t2(increment, std::ref(x));
t2.join();
std::cout << x << std::endl;
return 0;
}
输出:
Hello, world!
1
有时候我们可能不需要等待线程完成,而是希望它在后台运行。这时候我们可以使用t.detach()方法来分离线程。
#include
#include
void print_message(const std::string& message) {
std::cout << message << std::endl;
}
int main() {
std::thread t(print_message, "Thread 1");
t.detach();
std::cout << "Thread detached" << std::endl;
return 0;
}
Thread detached
Thread 1
可以是主进程完成之后在进行子进程
因为join和detach智能调用一次,所以可以使用joinable来判断是否可以使用该线程
针对一个线程,可以调用detach,或者join。两者是互斥的关系,也就说一旦调用了join,detach就不能再调用了,反之亦成立。判断是否已经使用过join或者detach可以用joinable。
std::thread t(print_message, "Thread 1");
std::cout << t.joinable() << std::endl;
t.join();
std::cout << "Thread detached" << std::endl;
std::cout << t.joinable() << std::endl;
1
Thread 1
Thread detached
0
int i=1;
std::thread t(foo, std::ref(i)) #std::thread t(foo, 1);
如果是直接浅拷贝传递临时变量给线程,那么线程在执行的时候,临时变量会被销毁
当不同的线程同事访问改写一个数据的时候,就可能出现数据竞争的关系,为避免数据竞争问题,可以使用同步机制()包括互斥量、条件变量、原子操作)来保证访问安全。
void func(int n) {
for (int i = 0; i < 10; ++i) {
//mtx.lock();
shared_data++;
std::cout << "Thread " << n
<< " increment shared_data to " << shared_data << std::endl;
//mtx.unlock();
}
}
int main() {
std::thread t1(func, 1);
std::thread t2(func, 2);
在不设置互斥锁的情况下,访问和修改是无序的
Thread 2 increment shared_data to 2
Thread 2 increment shared_data to 3
Thread 2 increment shared_data to 4
Thread 2 increment shared_data to 5
Thread 2 increment shared_data to 6
Thread 2 increment shared_data to 7
Thread 2 increment shared_data to 8
Thread 2 increment shared_data to 9
Thread 2 increment shared_data to 10
Thread 2 increment shared_data to 11
Thread 1 increment shared_data to 11
Thread 1 increment shared_data to 12
Thread 1 increment shared_data to 13
Thread 1 increment shared_data to 14
Thread 1 increment shared_data to 15
Thread 1 increment shared_data to 16
Thread 1 increment shared_data to 17
Thread 1 increment shared_data to 18
Thread 1 increment shared_data to 19
Thread 1 increment shared_data to 20
先调用 mtx.lock() 来获取互斥量的所有权,然后对 shared_data 变量进行累加操作,最后再调用 mtx.unlock() 来释放互斥量的所有权。
假设有两个线程 T1 和 T2,它们需要对两个互斥量 mtx1 和 mtx2 进行访问,而且需要按照以下顺序获取互斥量的所有权:
T1 先获取 mtx1 的所有权,再获取 mtx2 的所有权。
T2 先获取 mtx2 的所有权,再获取 mtx1 的所有权。
当两个都在等对方释放资源的时候就可能会造成死锁
void func1() {
mtx2.lock();
std::cout << "Thread 1 locked mutex 2" << std::endl;
mtx1.lock();
std::cout << "Thread 1 locked mutex 1" << std::endl;
mtx1.unlock();
std::cout << "Thread 1 unlocked mutex 1" << std::endl;
mtx2.unlock();
std::cout << "Thread 1 unlocked mutex 2" << std::endl;
}
void func2() {
mtx2.lock();
std::cout << "Thread 2 locked mutex 2" << std::endl;
mtx1.lock();
std::cout << "Thread 2 locked mutex 1" << std::endl;
mtx1.unlock();
std::cout << "Thread 2 unlocked mutex 1" << std::endl;
mtx2.unlock();
std::cout << "Thread 2 unlocked mutex 2" << std::endl;
}
在上述实例中,两者都先强调mtx2,再强调mtx1,所以谁先抢到mtx2谁先执行,还有个函数try_lock()其功能和joinable差不多。
Thread 1 locked mutex 2
Thread 1 locked mutex 1
Thread 1 unlocked mutex 1
Thread 1 unlocked mutex 2
Thread 2 locked mutex 2
Thread 2 locked mutex 1
Thread 2 unlocked mutex 1
Thread 2 unlocked mutex 2
指事务的不可分割性,一个事务的所有操作要么不间断地全部被执行,要么一个也没有执行。
其定义方式atomic x,在对它进行操作是原子性的,不会出现数据竞争问题
#include
#include
#include
std::atomic<int> count = 0;
void increment() {
for (int i = 0; i < 1000000; ++i) {
count++;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << count << std::endl;
return 0;
}