C++ 线程操作
线程是 Linux 操作系统中的一种轻量级进程,用于实现并发执行。线程可以共享进程的资源,包括内存、文件句柄等。在 C++ 中,线程操作由标准库提供支持,主要涉及以下几个头文件:
#include // 线程相关的库
#include // 互斥量相关的库
#include // 条件变量相关的库
创建线程
在 C++ 中,使用 std::thread 类创建新线程。创建线程的基本形式为:
std::thread t1(func, args...);
其中 func 是线程执行的函数,args… 是函数的参数列表。
示例:
#include
#include
void threadFunc(int n) {
std::cout << "Thread ID: " << std::this_thread::get_id()
<< ", n = " << n << std::endl;
}
int main() {
std::thread t1(threadFunc, 10);
t1.join(); // join后主线程将会被阻塞,等待线程结束
return 0;
}
上述代码中,threadFunc 函数被传递给 std::thread 类的构造函数创建一个新线程。线程执行函数中输出线程 ID 和传入的参数值。t1.join() 语句等待线程结束后才会继续执行主线程。
在多线程编程中,当多个线程同时访问共享资源时,容易出现竞态条件(Race Condition),导致程序出现不可预期的行为。为了避免这种情况,可以使用互斥量(Mutex)来保护共享资源,确保同一时间只有一个线程可以访问它。
互斥量使用 std::mutex 类实现,常用的方法有:
lock():获得互斥量的锁。
unlock():释放互斥量的锁。
示例:
#include
#include
#include
std::mutex mtx; // 定义互斥量
void threadFunc(int n) {
mtx.lock(); // 获得互斥量的锁
std::cout << "Thread ID: " << std::this_thread::get_id()
<< ", n = " << n << std::endl;
mtx.unlock(); // 释放互斥量的锁
}
int main() {
std::thread t1(threadFunc, 10);
std::thread t2(threadFunc, 20);
t1.join();
t2.join();
return 0;
}
在上述代码中,std::mutex 类型的 mtx 对象用于保护 threadFunc 函数中的输出操作,以避免同时输出导致的混乱。
在多线程编程中,有时需要让线程等待某个条件满足后再继续执行,这时可以使用条件变量(Condition Variable)来实现。
条件变量使用 std::condition_variable 类实现,常用的方法有:
示例:
#include
#include
#include
#include
std::mutex mtx; // 定义互斥量
std::condition_variable cv; // 定义条件变量
bool ready = false; // 条件变量状态标志
void threadFunc(int n) {
std::unique_lock<std::mutex> lock(mtx);
while (!ready) { // 等待条件变量
cv.wait(lock);
}
std::cout << "Thread ID: " << std::this_thread::get_id()
<< ", n = " << n << std::endl;
}
int main() {
std::thread t1(threadFunc, 10);
std::thread t2(threadFunc, 20);
// 设置条件变量状态标志
std::this_thread::sleep_for(std::chrono::seconds(2));
ready = true;
cv.notify_all(); // 唤醒所有等待条件变量的线程
t1.join();
t2.join();
return 0;
}
在上述代码中,std::condition_variable 类型的 cv 对象用于实现线程等待条件变量的功能。在 threadFunc 函数中,使用 cv.wait(lock) 等待条件变量。在 main 函数中,先等待一段时间后设置条件变量状态标志 ready 为 true,再通过 cv.notify_all() 唤醒所有等待条件变量的线程。
线程操作可以应用于很多场景,比如:
多线程下载文件:可以使用多个线程同时下载文件,提高下载速度。
多线程处理数据:可以使用多个线程同时处理数据,提高处理效率。
多线程编程游戏:可以使用多个线程处理游戏逻辑和渲染,提高游戏性能。
多线程爬虫:可以使用多个线程同时爬取网页,提高爬虫效率。
当然,使用线程操作时需要注意线程安全性问题,避免出现竞态条件等问题。同时也需要注意线程间通信的问题,确保线程间可以正确地传递信息。