在C++中,线程的同步与异步执行是多线程编程中的关键概念,它们影响着程序的执行流程和性能。以下是C++中线程同步与异步执行的一些关键点和技术:
同步执行意味着线程按照它们启动的顺序依次执行,一个线程完成后,下一个线程才开始执行。在C++中,可以通过`std::thread`来创建线程,并使用`join()`方法来同步线程:
```cpp
#include
#include
void syncFunction() {
std::cout << "Synchronous function execution" << std::endl;
}
int main() {
std::thread t(syncFunction);
t.join(); // 等待线程t完成
return 0;
}
```
异步执行意味着线程可以并行执行,不必等待前一个线程完成。在C++中,可以通过`std::async`或`std::thread`(不调用`join()`)来实现异步执行:
```cpp
#include
#include
void asyncFunction() {
std::cout << "Asynchronous function execution" << std::endl;
}
int main() {
std::future result = std::async(std::launch::async, asyncFunction);
result.get(); // 获取异步执行的结果
return 0;
}
```
线程同步是确保多个线程在访问共享资源时不会导致数据不一致或竞态条件的技术。C++11引入了多种同步原语,如`std::mutex`、`std::lock_guard`、`std::atomic`等:
```cpp
#include
#include
#include
std::mutex mtx; // 全局互斥锁
void printBlock(int n, char c) {
mtx.lock();
for (int i = 0; i < n; ++i) {
std::cout << c;
}
std::cout << '\n';
mtx.unlock();
}
int main() {
std::thread th1(printBlock, 50, '*');
std::thread th2(printBlock, 50, '$');
th1.join();
th2.join();
return 0;
}
```
线程间通信可以通过条件变量(`std::condition_variable`)实现,它允许线程在某个条件满足之前挂起,并在条件满足时被唤醒:
```cpp
#include // 包含标准输入输出流库,用于输出信息
#include // 包含线程库,用于创建和管理线程
#include // 包含互斥锁库,用于同步线程对共享资源的访问
#include // 包含条件变量库,用于线程间的同步
// 全局变量定义
std::mutex mtx; // 定义一个互斥锁mtx,用于保护共享资源
std::condition_variable cv; // 定义一个条件变量cv,用于线程间的同步
bool ready = false; // 定义一个布尔变量ready,初始值为false,用于表示工作是否准备好
// 定义一个函数do_work,它将在一个线程中执行
void do_work() {
std::unique_lock lk(mtx); // 创建一个unique_lock对象lk,它将互斥锁mtx上锁
cv.wait(lk, []{ return ready; }); // 使用条件变量cv等待,直到ready变为true
// 这里的lambda函数作为wait的谓词,当ready为true时,wait将返回
std::cout << "Work done" << std::endl; // 当ready为true时,输出"Work done"
}
// 定义一个函数go,它将在另一个线程中执行
void go() {
std::unique_lock lk(mtx); // 在go函数中创建一个unique_lock对象lk,它将互斥锁mtx上锁
ready = true; // 将ready设置为true,表示工作准备好了
cv.notify_one(); // 通知一个等待在条件变量cv上的线程继续执行
}
// 主函数
int main() {
// 创建一个线程worker,它将执行do_work函数
std::thread worker(do_work);
// 创建另一个线程boss,它将执行go函数
std::thread boss(go);
// 等待worker线程结束
worker.join();
// 等待boss线程结束
boss.join();
// 主函数返回0,表示程序正常退出
return 0;
}
```
线程池是一种管理线程的技术,它允许你重用线程而不是为每个任务创建和销毁线程,从而提高性能:
```cpp
#include
#include
#include
#include
#include
#include
class ThreadPool {
public:
ThreadPool(size_t);
template
auto enqueue(F&& f, Args&&... args);
~ThreadPool();
private:
// 省略线程池实现细节
};
// 使用线程池
int main() {
ThreadPool pool(4); // 创建包含4个工作线程的线程池
auto result = pool.enqueue([] {
std::cout << "Hello, world!" << std::endl;
});
return 0;
}
```
在C++中,线程同步与异步执行是多线程编程的基础,正确使用这些技术可以提高程序的性能和响应能力。
在C++中,检测线程是否完成执行通常涉及到使用`std::thread`对象的状态。`std::thread`提供了几种方法来检查线程的状态和状态信息。
以下是几种检测线程是否完成执行的方法:
### 1. 使用`join()`方法
最直接的方法是调用`std::thread`对象的`join()`方法。这个方法会阻塞调用线程,直到关联的线程执行完成。如果线程已经完成,`join()`会立即返回。
```cpp
#include
#include
void func() {
// 执行一些操作
}
int main() {
std::thread t(func);
// 做一些其他操作...
t.join(); // 等待线程t完成
std::cout << "Thread has finished execution." << std::endl;
return 0;
}
```
### 2. 使用`joinable()`方法
`joinable()`方法用于检查线程是否可被`join()`,即线程是否已经被启动并且还没有完成。如果线程已经完成或者没有被启动,`joinable()`将返回`false`。
```cpp
#include
#include
void func() {
// 执行一些操作
}
int main() {
std::thread t(func);
if (t.joinable()) {
// 线程还在执行
}
t.join(); // 等待线程完成
std::cout << "Thread has finished execution." << std::endl;
return 0;
}
```
### 3. 使用`get_id()`方法
`get_id()`方法返回线程的唯一标识符。如果线程已经完成,`get_id()`将返回一个特殊的空标识符(`std::thread::id()`)。通过比较线程的`get_id()`与`std::thread::id()`,可以检查线程是否已经完成。
```cpp
#include
#include
void func() {
// 执行一些操作
}
int main() {
std::thread t(func);
if (t.get_id() != std::thread::id()) {
// 线程还在执行
}
t.join(); // 等待线程完成
std::cout << "Thread has finished execution." << std::endl;
return 0;
}
```
### 4. 使用`std::future`和`std::promise`
如果你使用`std::async`或`std::future`来管理线程,可以通过`std::future`对象的`wait()`方法来等待线程完成,或者使用`std::async`的返回值