并发编程基础 - 并发编程的概念(C++)
前言
在当今多核处理器普及的时代,并发编程成为开发高性能应用程序的关键技术之一。无论是服务器端应用,桌面软件,还是移动应用,并发编程都扮演着重要角色。本文将详细介绍并发编程的基本概念,结合C++语言特性,帮助读者理解并掌握这一重要主题。
1. 什么是并发编程?
并发编程是指一个程序能够在同一时间段内执行多个任务的能力。这里的“多个任务”可以是不同的计算步骤、输入输出操作或与其他系统的交互等。值得注意的是,“同一时间段”并不严格意味着完全同时发生;它还包括交替快速地切换各个任务的情形,从宏观上看就像所有任务都在并行运行一样。
并发与并行的区别:
- 并发:指的是多个任务在同一时间段内被处理,它们之间可能交替执行。
- 并行:指的则是真正的多任务同时进行,通常需要硬件支持,如多核CPU。
对于开发者来说,理解和正确使用并发编程,可以充分利用现代计算机的硬件资源,提高程序的性能和响应速度。
2. C++中的线程
C++11标准引入了对多线程的支持,使得我们可以在C++中轻松实现并发编程。线程是操作系统能够进行运算调度的最小单位,一个进程由一个或多个线程组成。每个线程都有自己的栈空间和局部变量,但共享进程的全局数据和其他资源。
创建线程
在C++中,创建线程非常简单,只需要包含头文件<thread>
,然后使用std::thread
类:
#include <iostream>
#include <thread>
void print_hello() {
std::cout << "Hello, thread!" << std::endl;
}
int main() {
// 创建一个新的线程来执行print_hello函数
std::thread t(print_hello);
// 等待线程结束
if (t.joinable()) {
t.join();
}
return 0;
}
线程参数传递
有时我们需要给线程传递参数,这也可以通过构造函数完成:
void print_message(const std::string& message) {
std::cout << message << std::endl;
}
int main() {
std::string msg = "Hello from a thread!";
std::thread t(print_message, msg);
if (t.joinable()) {
t.join();
}
return 0;
}
使用lambda表达式创建线程
除了直接传递函数名外,还可以使用C++11引入的lambda表达式来定义更灵活的任务逻辑:
int main() {
int value = 42;
std::thread t([value]() {
std::cout << "Value is: " << value << std::endl;
});
if (t.joinable()) {
t.join();
}
return 0;
}
3. 同步机制
当多个线程访问共享资源时,为了防止竞争条件(Race Condition),必须采取适当的同步措施。C++提供了多种同步工具,比如互斥量(Mutex)、读写锁(Read-Write Locks)等。
互斥量 Mutex
最常用的同步原语就是互斥量,它可以确保同一时间只有一个线程可以访问受保护的数据:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx; // 定义一个互斥量
void print_block(int n, char c) {
std::lock_guard<std::mutex> lock(mtx); // 自动锁定和解锁
for (int i = 0; i < n; ++i) {
std::cout << c;
}
std::cout << '\n';
}
int main() {
std::thread th1(print_block, 50, '*');
std::thread th2(print_block, 50, '$');
th1.join();
th2.join();
return 0;
}
这里使用了std::lock_guard
自动管理锁的获取和释放,简化了代码,减少了出错的可能性。
总结
通过上述介绍,相信你已经对并发编程有了初步的认识,并且了解了如何在C++中创建线程以及基本的同步方法。当然,实际开发中还有很多细节需要注意,例如死锁问题、性能优化等,这些内容将在后续的文章中继续探讨。希望这篇博客能为你的并发编程之旅提供有价值的参考!
如果你有任何疑问或者想要了解更多相关内容,请随时留言交流!