上期回顾: 【C++】预处理器与宏及特殊类设计
个人主页:C_GUIQU
归属专栏:C++
目录
正文
1. 多线程基础
1.1 线程概念
在 C++ 中,线程是程序中独立的执行路径。多线程允许一个程序同时执行多个任务,从而提高程序的效率和响应能力。
1.2 创建线程
在 C++ 11 及以后,可以使用 std::thread
来创建线程。以下是一个简单的示例:
#include <iostream>
#include <thread>
void hello() {
std::cout << "Hello from thread " << std::this_thread::get_id() << std::endl;
}
int main() {
std::thread t(hello);
std::cout << "Hello from main thread " << std::this_thread::get_id() << std::endl;
t.join();
return 0;
}
在这个示例中,定义了一个函数 hello
,然后通过 std::thread
创建一个新的线程来执行这个函数。在主线程中输出主线程的 ID,新线程中输出新线程的 ID。最后通过 t.join()
等待新线程完成。
2. 线程参数传递
2.1 传递基本数据类型
可以向线程函数传递基本数据类型的参数。例如:
#include <iostream>
#include <thread>
void print_number(int num) {
std::cout << "Number in thread: " << num << std::endl;
}
int main() {
int number = 42;
std::thread t(print_number, number);
t.join();
return 0;
}
这里向 print_number
函数传递一个整数参数。
2.2 传递引用类型
当需要在线程函数中修改参数的值时,可以传递引用。但要注意确保引用所指向的对象在整个线程执行期间都有效。
#include <iostream>
#include <thread>
void increment(int& num) {
num++;
std::cout << "Incremented number in thread: " << num << std::endl;
}
int main() {
int number = 10;
std::thread t(increment, std::ref(number));
t.join();
std::cout << "Number in main thread after increment: " << number << std::endl;
return 0;
}
通过 std::ref
来传递引用,这样在线程中对参数的修改会反映到主线程中的变量。
3. 线程同步
3.1 互斥量(Mutex)
互斥量用于保护共享资源,防止多个线程同时访问。以下是使用 std::mutex
的示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mutex_lock;
int shared_variable = 0;
void increment_shared_variable() {
std::lock_guard<std::mutex> guard(mutex_lock);
shared_variable++;
}
int main() {
std::thread t1(increment_shared_variable);
std::thread t2(increment_shared_variable);
t1.join();
t2.join();
std::cout << "Shared variable value: " << shared_variable << std::endl;
return 0;
}
这里使用 std::lock_guard
结合 std::mutex
来确保每次只有一个线程能够访问 shared_variable
。
3.2 条件变量(Condition Variable)
条件变量用于线程间的同步,一个线程等待某个条件满足,另一个线程在条件满足时通知等待的线程。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mutex_lock;
std::condition_variable condition;
bool ready = false;
void waiting_thread() {
std::unique_lock<std::mutex> lock(mutex_lock);
condition.wait(lock, [] { return ready; });
std::cout << "Waiting thread is notified." << std::endl;
}
void signaling_thread() {
{
std::lock_guard<std::mutex> guard(mutex_lock);
ready = true;
}
condition.notify_one();
}
int main() {
std::thread t1(waiting_thread);
std::thread t2(signaling_thread);
t1.join();
t2.join();
return 0;
}
在这个示例中,waiting_thread
等待条件变量,signaling_thread
在满足条件时通知它。
4. 线程池
4.1 线程池概念
线程池是一种用于管理和复用线程的机制。它包含一组预先创建好的线程,可以接受任务并执行。
4.2 简单线程池实现
以下是一个简单的线程池实现的部分代码:
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
class ThreadPool {
public:
ThreadPool(size_t num_threads) {
for (size_t i = 0; i < num_threads; ++i) {
threads.push_back(std::thread(&ThreadPool::worker, this));
}
}
~ThreadPool() {
{
std::lock_guard<std::mutex> guard(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread& th : threads) {
if (th.joinable()) {
th.join();
}
}
}
void enqueue(std::function<void()> task) {
{
std::lock_guard<std::mutex> guard(queue_mutex);
tasks.push(task);
}
condition.notify_one();
}
private:
std::vector<std::thread> threads;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop = false;
void worker() {
while (true) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this] { return stop ||!tasks.empty(); });
if (stop && tasks.empty()) {
return;
}
task = tasks.front();
tasks.pop();
}
task();
}
}
};
int main() {
ThreadPool pool(4);
for (int i = 0; i < 8; ++i) {
pool.enqueue([i] {
std::cout << "Task " << i << " is running in thread " << std::this_thread::get_id() << std::endl;
});
}
return 0;
}
这个线程池类创建了指定数量的线程,通过 enqueue
函数可以向线程池添加任务,线程池中的线程会不断从任务队列中获取任务并执行。
结语
感谢您的阅读!期待您的一键三连!欢迎指正!