NJ指令基准手册多线程编程:深入探索并发编程的10大艺术
发布时间: 2024-12-15 07:33:06 阅读量: 1 订阅数: 3
![NJ指令基准手册多线程编程:深入探索并发编程的10大艺术](https://learningos.cn/os-lectures/lec11/figs/threadvsroutine21.png)
参考资源链接:[NJ系列指令基准手册:FA设备自动化控制指南](https://wenku.csdn.net/doc/64603f33543f8444888d9058?spm=1055.2635.3001.10343)
# 1. 多线程编程概述
多线程编程是指在同一程序中,允许两个或两个以上的线程同时运行。它允许多个线程共享单个应用程序的地址空间和资源,同时允许每个线程执行不同的任务。这种编程范式可以极大提升应用程序的性能和响应速度,特别是对于那些可以并行处理的任务。然而,同时它也引入了线程安全、死锁、资源竞争等并发编程的复杂问题。理解多线程编程的基础概念和原则是设计健壮且高效并发应用的关键。在本章中,我们将从多线程编程的基础知识讲起,逐步深入到它的原理、特点和应用场景。
# 2. 线程的创建与管理
### 线程的基本概念与生命周期
#### 线程的创建与启动
在多线程编程中,线程的创建是核心操作之一。线程的创建可以由操作系统提供的API来实现,其创建过程大致包括分配线程控制块、初始化线程环境、以及将线程加入到可调度线程池中等步骤。
以下是使用C++中的`std::thread`类创建和启动线程的基本示例代码:
```cpp
#include <iostream>
#include <thread>
void threadFunction() {
std::cout << "线程执行中..." << std::endl;
}
int main() {
std::thread myThread(threadFunction);
myThread.join();
std::cout << "线程执行完毕。" << std::endl;
return 0;
}
```
该代码创建了一个新线程并执行了`threadFunction`函数。使用`std::thread`类的构造函数传递了线程函数指针,然后通过调用`join`方法等待线程执行结束。
#### 线程的终止与回收
线程的终止可以通过多种方式实现,其中最常见的是从线程函数中返回,从而自动销毁线程。线程对象在生命周期结束时,资源会自动回收。
例如:
```cpp
void threadFunction() {
// 执行任务...
return; // 线程结束,自动回收资源
}
int main() {
std::thread myThread(threadFunction);
myThread.join();
// 线程对象myThread生命周期结束,其资源被自动回收
return 0;
}
```
在上述示例中,`myThread`线程在`threadFunction`函数执行完毕后,通过返回自动结束其生命周期。`main`函数中`myThread`对象销毁时,线程资源被自动回收。
### 线程同步机制
在多线程编程中,线程同步是保证线程安全的重要手段。通过同步机制可以避免多线程对共享资源的并发访问导致的数据不一致问题。
#### 互斥锁(Mutex)
互斥锁是一种简单的同步机制,用于控制对共享资源的互斥访问。当一个线程获取锁后,其他线程必须等待,直到该线程释放锁。
以下是使用互斥锁的一个简单示例:
```cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void printNumbers(int number) {
mtx.lock();
std::cout << "Number: " << number << std::endl;
mtx.unlock();
}
int main() {
std::thread t1(printNumbers, 1);
std::thread t2(printNumbers, 2);
t1.join();
t2.join();
return 0;
}
```
在这个例子中,我们使用`std::mutex`来互斥访问共享的`std::cout`资源。`lock()`方法用于获取锁,`unlock()`方法用于释放锁。
#### 信号量(Semaphore)
信号量是一种更通用的同步机制,它可以控制多个线程同时访问特定数量的资源。与互斥锁不同,信号量允许一定的并发量。
这里是一个简单的信号量使用示例:
```cpp
#include <semaphore>
#include <thread>
#include <iostream>
std::semaphore sem(5);
void threadFunc(int id) {
sem.acquire();
std::cout << "Thread " << id << " is accessing resource.\n";
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟资源访问时间
sem.release();
}
int main() {
std::thread t[10];
for(int i = 0; i < 10; ++i) {
t[i] = std::thread(threadFunc, i+1);
}
for(int i = 0; i < 10; ++i) {
t[i].join();
}
return 0;
}
```
在这个例子中,信号量`sem`初始化为5,表示最多允许5个线程同时访问资源。`acquire`方法用于获取信号量,`release`方法用于释放信号量。
#### 条件变量(Condition Variable)
条件变量提供了一种线程间通信的方式,它允许线程在某些条件未满足时等待,当条件满足时由其他线程唤醒。
一个条件变量使用场景的简单示例:
```cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cond;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) {
cond.wait(lck);
}
std::cout << "Thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cond.notify_all();
}
int main() {
std::thread threads[10];
for(int i = 0; i < 10; ++i) {
threads[i] = std::thread(print_id, i+1);
}
std::cout << "10 threads ready to race...\n";
go();
for(auto& th : threads) {
th.join();
}
return 0;
}
```
在这个例子中,线程在`print_id`函数中等待条件变量`cond`,直到`ready`变为`true`。当`ready`变为`true`后,所有线程都会被`cond.notify_all()`唤醒。
### 线程的高级管理技术
线程的高级管理包括线程池的实现与应用、线程优先级与调度、以及线程局部存储(Thread Local Storage)等。
#### 线程池的实现与应用
线程池是一种线程管理技术,可以减少频繁创建和销毁线程的开销,提高程序性能。线程池中的线程等待任务分配,任务完成后再返回线程池等待下一个任务。
下面是一个简单的线程池实现示例:
```cpp
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <future>
class ThreadPool {
public:
ThreadPool(size_t threads) : stop(false) {
for(size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
for(;;) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
this->condition.wait(lock, [this] {
return this->stop || !this->tasks.empty();
});
if(this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
});
}
}
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
auto task = std::make_shared< std::packaged_task<return_type()> >(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->
```
0
0