C++ std::thread使用

本文详细介绍了C++标准库中的线程管理工具std::thread的使用方法,包括线程的创建、分离、赋值操作、成员函数get_id()、joinable()、detach()、swap()以及原子变量与线程安全的实现。通过示例代码,展示了如何在C++中高效地进行多线程编程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <thread>
#include <chrono>
#include <functional>

class MyClass {
public:
    // 成员函数B,带一个参数
    void memberFunctionB(int value) {
        std::cout << "Member function B called with value: " << value << std::endl;
        // 模拟一些耗时操作
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }

    // 成员函数A,创建线程并调用成员函数B
    void memberFunctionA(int param) {
        // 创建一个线程来调用成员函数B
        std::thread t(&MyClass::memberFunctionB, this, param);

        // 分离线程以使其非阻塞
        t.detach();

        // 继续执行其他操作
        std::cout << "Member function A continues execution." << std::endl;
    }
};

int main() {
    MyClass obj;

    // 调用成员函数A
    obj.memberFunctionA(42);

    // 等待一段时间以确保线程有时间执行(仅用于演示)
    std::this_thread::sleep_for(std::chrono::seconds(3));

    return 0;
}

#include <iostream>
#include <thread>
#include <chrono>

class MyClass {
public:
    // 成员函数B,带一个参数
    void memberFunctionB(int value) {
        std::cout << "Member function B called with value: " << value << std::endl;
        // 模拟一些耗时操作
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }

    // 成员函数A,创建线程并调用成员函数B
    void memberFunctionA(int param) {
        // 使用 lambda 表达式来创建线程并调用成员函数B
        std::thread([this, param]() {
            memberFunctionB(param);
        }).detach(); // 分离线程使其非阻塞

        // 继续执行其他操作
        std::cout << "Member function A continues execution." << std::endl;
    }
};

int main() {
    MyClass obj;

    // 调用成员函数A
    obj.memberFunctionA(42);

    // 等待一段时间以确保线程有时间执行(仅用于演示)
    std::this_thread::sleep_for(std::chrono::seconds(3));

    return 0;
}

c++ 11 之后有了标准的线程库:std::thread。通过c++11中的线程库创建线程,极为方便,且跨平台,是语言层面的。之前跨平台的多线程开发中,多使用boost 相关第三方库。

在main函数中 启动另外线程调用 C++ 匿名函数、参数

#include <iostream>
#include <thread>

int main() {
    std::thread t([](){
        // 在这里编写你的匿名函数的代码
        std::cout << "Hello from the new thread!" << std::endl;
    });

    // 主线程继续执行其他操作

    t.join(); // 等待新线程执行完毕

    return 0;
}

1.std::thread 构造函数

默认构造函数 		thread() noexcept;
初始化构造函数 	template <class Fn, class... Args>
explicit thread(Fn&& fn, Args&&... args);
拷贝构造函数 [deleted] 	thread(const thread&) = delete;
Move 构造函数 	thread(thread&& x) noexcept;

(1).默认构造函数,创建一个空的 std::thread 执行对象。
(2).初始化构造函数,创建一个 std::thread 对象,该 std::thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。
(3).拷贝构造函数(被禁用),意味着 std::thread 对象不可拷贝构造。
(4).Move 构造函数,move 构造函数(move 语义是 C++11 新出现的概念,详见附录),调用成功之后 x 不代表任何 std::thread 执行对象。
注意:可被 joinable 的 std::thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.

std::thread 各种构造函数例子如下:

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>

void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread " << n << " executing\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));
    }
}

int main()
{
    int n = 0;
    std::thread t1; // t1 is not a thread,t1不是一个thread
    std::thread t2(f1, n + 1); // pass by value,按照值传递
    std::thread t3(f2, std::ref(n)); // pass by reference,引用
    std::thread t4(std::move(t3)); // t4 is now running f2(). t3 is no longer a thread,t4执行t3,t3不是thread
    t2.join();
    t4.join();
    std::cout << "Final value of n is " << n << '\n';
}

2.std::thread 赋值操作

Move 赋值操作 	thread& operator=(thread&& rhs) noexcept;
拷贝赋值操作 [deleted] 	thread& operator=(const thread&) = delete; 

(1).Move 赋值操作(1),如果当前对象不可 joinable,需要传递一个右值引用(rhs)给 move 赋值操作;如果当前对象可被 joinable,则会调用 terminate() 报错。’
(2).拷贝赋值操作(2),被禁用,因此 std::thread 对象不可拷贝赋值。

请看下面的例子:

#include <stdio.h>
#include <stdlib.h>

#include <chrono>    // std::chrono::seconds
#include <iostream>  // std::cout
#include <thread>    // std::thread, std::this_thread::sleep_for

void thread_task(int n) {
    std::this_thread::sleep_for(std::chrono::seconds(n));
    std::cout << "hello thread "
        << std::this_thread::get_id()
        << " paused " << n << " seconds" << std::endl;
}

int main(int argc, const char *argv[])
{
    std::thread threads[5];
    std::cout << "Spawning 5 threads...\n";
    for (int i = 0; i < 5; i++) {
        threads[i] = std::thread(thread_task, i + 1);
    }
    std::cout << "Done spawning threads! Now wait for them to join\n";
    for (auto& t: threads) {
        t.join();
    }
    std::cout << "All threads joined.\n";

    return EXIT_SUCCESS;
}

3.其他成员函数

3.1 get_id()

获取线程 ID,返回一个类型为 std::thread::id 的对象。

请看下面例子:

//test.cpp
#include <iostream>
#include <thread>
#include <chrono> //该头文件详情可参考:https://www.cnblogs.com/jwk000/p/3560086.html

void foo()
{
  std::this_thread::sleep_for(std::chrono::seconds(1));
}

int main()
{
  std::thread t1(foo);
  std::thread::id t1_id = t1.get_id();

  std::thread t2(foo);
  std::thread::id t2_id = t2.get_id();

  std::cout << "t1's id: " << t1_id << '\n';
  std::cout << "t2's id: " << t2_id << '\n';

  t1.join();
  t2.join();
  return 0;
}
//编译g++ -std=c++11 -pthread test.cpp -o test

从std::thread::id取得int值线程id

std::thread::id tid = std::this_thread::get_id();
_Thrd_t t = *(_Thrd_t*)(char*)&tid ;
unsigned int nId = t._Id

参考资料:https://www.cnblogs.com/yc-only-blog/p/9178935.html

3.2 joinable()

检查线程是否可被 join。检查当前的线程对象是否表示了一个活动的执行线程,由默认构造函数创建的线程是不能被 join 的。另外,如果某个线程 已经执行完任务,但是没有被 join 的话,该线程依然会被认为是一个活动的执行线程,因此也是可以被 join 的。

#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);//此时子线程并不执行,在调json()或detach()后才执行
    std::cout << "after starting, joinable: " << t.joinable() << '\n';
 
    t.join();//说明:如果此处不调用join(),也不调用detach(),编译执行程序就会提示 terminate called without an active exception

    std::cout << "after joining, joinable: " << t.joinable() << '\n';
}
//join: Join 线程,调用该函数会阻塞当前线程,直到由 *this 所标示的线程执行完毕 join 才返回。

std::thread “terminate called without an active exception”请参考如下接:
https://www.cnblogs.com/little-ant/p/3312841.html

3.3 detach()

Detach 线程,将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。

调用 detach 函数之后:

*this 不再代表任何的线程执行实例。
joinable() == false
get_id() == std::thread::id()

另外,如果出错或者 joinable() == false,则会抛出 std::system_error。

#include <iostream>
#include <chrono>
#include <thread>
 
void independentThread() 
{
    std::cout << "Starting concurrent thread.\n";
    std::this_thread::sleep_for(std::chrono::seconds(2));
    std::cout << "Exiting concurrent thread.\n";
}
void threadCaller() 
{
    std::cout << "Starting thread caller.\n";
    std::thread t(independentThread);
    t.detach();
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Exiting thread caller.\n";
}
int main() 
{
    threadCaller();
    std::this_thread::sleep_for(std::chrono::seconds(5));
}

3.4 swap()

Swap 线程,交换两个线程对象所代表的底层句柄(underlying handles)。

#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()
{
    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::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;
 
    t1.swap(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;
 
    t1.join();
    t2.join();
}
执行结果如下:

thread 1 id: 1892
thread 2 id: 2584
after std::swap(t1, t2):
thread 1 id: 2584
thread 2 id: 1892
after t1.swap(t2):
thread 1 id: 1892
thread 2 id: 2584

3.5 native_handle

返回 native handle(由于 std::thread 的实现和操作系统相关,因此该函数返回与 std::thread 具体实现相关的线程句柄,例如在符合 Posix 标准的平台下(如 Unix/Linux)是 Pthread 库)。

3.6 hardware_concurrency [static]

检测硬件并发特性,返回当前平台的线程实现所支持的线程并发数目,但返回值仅仅只作为系统提示(hint)。

#include <iostream>
#include <thread>
 
int main() {
    unsigned int n = std::thread::hardware_concurrency();
    std::cout << n << " concurrent threads are supported.\n";
}

4.std::this_thread 命名空间中相关辅助函数介绍

4.1 get_id()

获取线程 ID。

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    std::thread t1(foo);
    std::thread::id t1_id = t1.get_id();
 
    std::thread t2(foo);
    std::thread::id t2_id = t2.get_id();
 
    std::cout << "t1's id: " << t1_id << '\n';
    std::cout << "t2's id: " << t2_id << '\n';
 
    t1.join();
    t2.join();
}

4.2 yield()

当前线程放弃执行,操作系统调度另一线程继续执行。

#include <iostream>
#include <chrono>
#include <thread>

// "busy sleep" while suggesting that other threads run 
// for a small amount of time
void little_sleep(std::chrono::microseconds us)
{
  auto start = std::chrono::high_resolution_clock::now();
  auto end = start + us;
  do {
      std::this_thread::yield();//让cpu执行其他空闲的线程
  } while (std::chrono::high_resolution_clock::now() < end);
}

int main()
{
  auto start = std::chrono::high_resolution_clock::now();

  little_sleep(std::chrono::microseconds(100));

  auto elapsed = std::chrono::high_resolution_clock::now() - start;
  std::cout << "waited for "
            << std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
            << " microseconds\n";
}

4.3 sleep_until()

线程休眠至某个指定的时刻(time point),该线程才被重新唤醒。

template< class Clock, class Duration >
void sleep_until( const std::chrono::time_point<Clock,Duration>& sleep_time );

4.4 sleep_for()

线程休眠某个指定的时间片(time span),该线程才被重新唤醒,不过由于线程调度等原因,实际休眠时间可能比 sleep_duration 所表示的时间片更长。

#include <iostream>
#include <chrono>
#include <thread>

int main()
{
  std::cout << "Hello waiter" << std::endl;
  std::chrono::milliseconds dura( 2000 );
  std::this_thread::sleep_for( dura );
  std::cout << "Waited 2000 ms\n";
}

5.std::thread堆栈使用

#include <iostream>
#include <thread>
using namespace std;
void show()
{
	cout << "hello cplusplus!" << endl;
}
int main()
{
	//栈上
	thread t1(show);   //根据函数初始化执行
	thread t2(show);
	thread t3(show);
	t1.join();
	t2.join();
	t3.join();
	//线程数组
	thread threads[3]{thread(show), thread(show), thread(show)}; 
	for (auto& t: threads) 
	{ 
		t.join();
	}
	
	//堆上
	thread *pt1(new thread(show));
	thread *pt2(new thread(show));
	thread *pt3(new thread(show));
	pt1->join();
	pt2->join();
	pt3->join();
	//线程指针数
	thread *pthreads(new thread[3]{thread(show), thread(show), thread(show)});
	

	delete pt1;
	delete pt2;
	delete pt3;
	// delete [] pthreads;//这里直接delete会导致异常退出,因为线程没有join(),也没有detach()

	
	int threadNum = 3;
	thread* t = new thread[threadNum];
	if(t)
	{
		for ( int i = 0; i < threadNum; i++){
        	t[i] = thread(show);    
	    }

	    for ( int i = 0; i < threadNum; i++){
	        //t[i].detach(); //主进程不等子进程运行完
	        t[i].join();        //主进程等
	    }
	}
	delete [] t;
	return 0;
}

注意事项:
1.std::thread在栈内创建后,需要在同一个作用域内调用join() 或者 detach(), 否则退出作用域后,程序会异常退出, 具体原因如下

~thread()
{
	if (joinable())
		std::terminate();
}

其中的std::terminate()就是用来终止进程的调用。由于std::thread创建后默认是joinable的, 所以需要调用join()或者detach() 来使线程变成非joinable的状态, 具体使用join()还是detach() 取决于实际需求, 如果需要等待线程完成才能继续,那就使用join()来等待, 如果需要立刻返回继续其他操作, 那就调用detach()来脱离对线程的管理, 两者必须选一个。

2.调用new 创建的std::thread, 禁止直接使用delete, 需要在调用delete之前,调用 join()或者 detach() (如果创建线程后立刻调用了这两个函数中任意一个, 可以不再调用, 但是为了保险起见, 需要加上if(joinable()) 的判断), 原因见上一条。

6.std::thread 线程执行体

std::thread 执行体类似boost::thread, 并不要求是普通的函数,任何可调用的对象都可,具体接受下面四种:

  1. 普通函数
  2. 函数对象
  3. 类成员函数
  4. lambda 函数(匿名函数)
    分别使用举例如下:

(1) 普通函数

void hello() //不带参数 
{
	//do whatever you want 
} 
void hello(std::string name) //带参数 
{
	//do whatever you want using parameter in 
} 
std::thread thread1(hello); 
std::thread thread2(hello, "test");

(2) 函数对象

class Hello // 不带参数 
{
	public: Hello(){} 

	//over ride operator() 
	void operator()() const 
	{
		//do whatever you want
	} 
};

class Hello {
	public: Hello() {} 

	//over ride operator() 
	void operator()(const std::string name) const 
	{
		// do whatever you want using parameter in
	} 
};

std::thread thread3(Hello()); 
std::thread thread4(Hello(), "test");

(3) 类成员函数

class Hello {
	public: entity() 
	{
		// do whatever you want 
	} 

	//over ride operator() 
	void entity(const std::string name) 
	{
		// do whatever you want using parameter in name
	} 
};

Hello obj;
std::thread thread5(&Hello::entity, &obj);
std::thread thread6(&Hello::entity,  &obj, "test");
// std::thread thread5(&Hello::entity, this);
// std::thread thread6(&Hello::entity,  this, "test");

此种构造也可以借助std::bind使用另外一种方式:

std::thread  thread5(std::bind(&Hello::entity, &obj));
std::thread  thread6(std::bind(&Hello::entity,  &obj, "test"));

(4) lambda 函数

std::thread thread7([](T var1, T var2){ 
	//do whatever you want using parameter var1 var2
}, realValue1, readValue2);

//某匿名函数定义 
//auto fun = [](const char *str) {cout << str << endl; };

7.原子变量与线程安全

示例1:

#include <iostream>
#include <thread>
using namespace std;
const int N = 100000000;
int num = 0;
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();//join之后开始执行子线程
	t2.join();//join之后开始执行子线程
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=100445432,用时 1013773 us
//注意linux下clock()单位是微妙,windows下clock()单位是毫秒

从上述代码执行的结果,发现结果并不是预计的200000000,这是由于线程之间发生冲突,从而导致结果不正确。为了解决此问题(多线程同时操作同一份数据),有以下方法:
(1)互斥量。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
const int N = 100000000;
int num = 0;
mutex m;
void run()
{
	for (int i = 0; i < N; i++)
	{
		m.lock();
		num++;
		m.unlock();
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 40520541 us

通过互斥量后运算结果正确,但是计算速度很慢,原因主要是互斥量加解锁需要时间。
互斥量详细内容 请参考C++11 并发之std::mutex
(2)原子变量。
例如:

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
const int N = 100000000;
atomic_int num{ 0 };//不会发生线程冲突,线程安全
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	thread t2(run);
	t1.join();
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 7111836 us

通过原子变量后运算结果正确,计算速度一般。
(3)通过控制 join位置 。

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
const int N = 100000000;
int num = 0;
void run()
{
	for (int i = 0; i < N; i++)
	{
		num++;
	}
}
int main()
{
	clock_t start = clock();
	thread t1(run);
	t1.join();
	thread t2(run);
	t2.join();
	clock_t end = clock();
	cout << "num=" << num << ",用时 " << end - start << " us" << endl;
	return 0;
}
//运行结果:
//num=200000000,用时 485837 us

运算结果正确,计算速度也很理想。看似没有什么问题,实际上适用场景非常有限,仅适用于一个线程去控制一份数据的情况,大型项目中线程层级关系较多,还是通过数据互斥锁或者设置原子变量的方法来控制

编译 g++ -std=c++11 -pthread test.cpp -o test.exe

参考资料:

示例

// Linux编译:g++ test_thread.cpp -lpthread
#include <iostream>
#include <thread>
#include <atomic>
#include <functional>
#include <mutex>

class CTestThread
{
private:
    /* data */
public:
   
void startThread()
{
    std::lock_guard<std::mutex> g(m_threadMtx);
    if(!m_p_thread){
        m_running = true;
        m_p_thread = new std::thread(std::bind(&CTestThread::runThread,this));
    }
}
void stopThread()
{
    std::lock_guard<std::mutex> g(m_threadMtx);
    if(m_p_thread){
        m_running = false;
        m_p_thread->join();
        delete m_p_thread;
        m_p_thread = nullptr;
    }
}
void runThread()
{
    int num = 0;
    while(m_running)
    {
        std::cout << "thread id:" << std::this_thread::get_id() << " num: " << num++ << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
}


void startThread2()
{
    if(!m_threadrunning){
        m_threadrunning = true;
        m_thread = std::move(std::thread(std::bind(&CTestThread::runThread,this)));
    }
}
void stopThread2()
{
    if(m_threadrunning){
        m_threadrunning = false;
        if (m_thread.joinable())
            m_thread.join();
    }
}

void startThread3()
{
    if(!m_threadrunning){
        m_threadrunning = true;
        m_thread = std::move(std::thread([this](){runThread();}));
    }
}
void stopThread3()
{
    if(m_threadrunning){
        m_threadrunning = false;
        if (m_thread.joinable())
            m_thread.join();
    }
}
 
private:
    std::mutex m_threadMtx;
    std::thread *m_p_thread = nullptr;
    bool m_running = false;


    std::thread m_thread;
    bool m_threadrunning = false;
};

void hello(std::string msg)\
{
    std::cout << "hello  " << msg << std::endl;
}

int main(int argc, char* argv[])
{
    CTestThread testThread;
    testThread.startThread();
    testThread.startThread2();

    CTestThread testThread3;
    testThread3.startThread3();


    std::thread th([]()->void{
        int count = 0;
        while(1){
            count++;
            std::cout << "count: " << count << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    });
    th.detach();

    std::thread th2([=](){
        int age = 0;
        while(1){
            age++;
            std::cout << "age: " << age << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    });
    th2.join(); // 线程不退出会阻塞在这里

    std::thread th4(hello, "LiMing");


// std::thread
// std::bind
// std::move
// 匿名函数
}
<think>我们根据用户的问题和提供的参考资料,详细讲解C++std::thread使用,包括线程创建、管理、同步机制等。 参考资料主要涉及[^1][^2][^3][^4],我们将结合这些内容进行讲解。 内容大纲: 1. 线程创建使用函数指针、Lambda、函数对象、成员函数等 2. 线程管理:join和detach 3. 线程同步:互斥锁(std::mutex)和条件变量(std::condition_variable)等 4. 参数传递的注意事项 5. 线程局部存储(thread_local) 6. 异常处理 我们将按照上述结构详细展开,并给出代码示例。</think>### C++ `std::thread` 使用详解:线程创建与管理 C++11 引入的 `<thread>` 头文件提供了强大的多线程支持,其中 `std::thread` 是线程管理的核心类。以下是详细使用指南: --- #### 一、线程创建方式 线程可通过多种可调用对象创建: 1. **函数指针** ```cpp void task(int param) { std::cout << "线程执行: " << param << std::endl; } int main() { std::thread t(task, 42); // 创建线程并传递参数 t.join(); } ``` 2. **Lambda 表达式**(推荐) ```cpp std::thread t([](const std::string& msg) { std::cout << "Lambda线程: " << msg << std::endl; }, "Hello Thread"); ``` 3. **函数对象(Functor)** ```cpp struct Task { void operator()(int x) const { std::cout << "函数对象: " << x*x << std::endl; } }; std::thread t(Task{}, 5); // 传递函数对象实例 ``` 4. **类成员函数** ```cpp class Worker { public: void run(const std::string& data) { std::cout << "成员函数线程: " << data << std::endl; } }; Worker w; std::thread t(&Worker::run, &w, "Data"); // 需传递对象指针[^3] ``` --- #### 二、线程生命周期管理 1. **`join()`**:阻塞当前线程直到目标线程完成 ```cpp std::thread t([]{ /* 任务 */ }); t.join(); // 主线程在此等待 ``` 2. **`detach()`**:分离线程(后台运行,无法再控制) ```cpp std::thread t([]{ /* 长时间任务 */ }); t.detach(); // 主线程继续执行 ``` > ⚠️ 警告:未`join()`或`detach()`的线程析构时会调用`std::terminate()`[^2] 3. **`joinable()`**:检查线程是否可管理 ```cpp if (t.joinable()) { t.join(); // 安全操作 } ``` --- #### 三、线程同步机制 避免数据竞争需使用同步原语: 1. **互斥锁 (`std::mutex`)** ```cpp std::mutex mtx; int counter = 0; void safe_increment() { std::lock_guard<std::mutex> lock(mtx); // RAII自动解锁 ++counter; } ``` 2. **条件变量 (`std::condition_variable`)** 实现线程间通信: ```cpp std::condition_variable cv; std::mutex mtx; bool data_ready = false; // 生产者线程 void producer() { std::lock_guard<std::mutex> lock(mtx); data_ready = true; cv.notify_one(); // 通知消费者 } // 消费者线程 void consumer() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{ return data_ready; }); // 阻塞直到条件满足 } ``` --- #### 四、参数传递注意事项 1. **默认按值传递**:参数被复制到线程独立内存空间 ```cpp int x = 10; std::thread t([](int a){ a *= 2; }, x); // x值不变 ``` 2. **引用传递需用 `std::ref` 包装** ```cpp int y = 20; std::thread t([](int& b){ b *= 2; }, std::ref(y)); // y变为40 ``` 3. **移动语义优化大对象** ```cpp std::vector<int> big_data(1000); std::thread t([](std::vector<int>&& data){ // 使用移动后的数据 }, std::move(big_data)); // 转移所有权 ``` --- #### 五、线程局部存储 (`thread_local`) 创建线程私有变量: ```cpp thread_local int thread_id = 0; // 每个线程独立副本 void print_id() { std::cout << "线程ID: " << thread_id++ << std::endl; } int main() { std::thread t1(print_id); // 输出0 std::thread t2(print_id); // 输出0(非1) t1.join(); t2.join(); } ``` --- #### 六、异常处理 线程内异常需捕获处理,否则导致程序终止: ```cpp void risky_task() { try { throw std::runtime_error("线程内部错误"); } catch (const std::exception& e) { std::cerr << "捕获异常: " << e.what() << std::endl; } } ``` --- ### 最佳实践 1. 优先使用 RAII 包装器(如 `std::lock_guard`) 2. 避免全局变量,使用参数传递数据 3. 用 `std::async` 替代 `std::thread` 实现任务并行(简化资源管理)[^4] 4. C++20 推荐 `std::jthread`(自动管理生命周期) ```cpp // std::async 示例 auto future = std::async(std::launch::async, []{ return std::sqrt(2.0); // 异步计算 }); double result = future.get(); // 获取结果 ``` --- ### 相关问题 1. 如何实现线程池以提高大量小任务的性能? 2. `std::atomic` 在无锁编程中如何应用? 3. 多线程调试有哪些常用工具和技巧? 4. C++20 协程如何简化异步编程模型? > 源码示例在 GCC/Clang 需编译选项:`-std=c++11 -pthread` > MSVC 需启用:`/std:c++latest /EHsc` [^1]: 线程创建方式与参数传递机制 [^2]: 线程生命周期管理关键点 [^3]: 类成员函数线程化实现 [^4]: 高级异步任务处理方案
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值