Linux C++中如何进行并发控制
在Linux环境下使用C++进行并发控制,可以采用多种机制来确保线程安全和管理多个线程之间的交互。以下是几种常用的方法和示例:
1. 使用互斥锁(Mutex)
互斥锁用于保护共享资源,防止多个线程同时访问导致的数据竞争。
示例代码:
#include
#include
#include
std::mutex mtx; // 全局互斥锁
int shared_variable = 0;
void increment() {
mtx.lock(); // 加锁
++shared_variable;
mtx.unlock(); // 解锁
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Shared Variable: " << shared class="hljs-keyword">return 0;
}
使用std::lock_guard
简化锁管理:
#include
#include
#include
std::mutex mtx;
int shared_variable = 0;
void increment() {
std::lock_guard lock(mtx); // RAII方式自动管理锁
++shared_variable;
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Shared Variable: " << shared class="hljs-keyword">return 0;
}
2. 使用条件变量(Condition Variables)
条件变量用于线程间的同步,允许一个线程等待某个条件成立,而另一个线程在条件满足时通知等待的线程。
示例代码:
#include
#include
#include
#include
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void worker() {
std::unique_lock lock(mtx);
cv.wait(lock, []{ return ready; }); // 等待条件变量
std::cout << "Worker thread is processing data.\n";
}
void trigger() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟一些工作
{
std::lock_guard lock(mtx);
ready = true;
}
cv.notify_one(); // 通知等待的线程
}
int main() {
std::thread t1(worker);
std::thread t2(trigger);
t1.join();
t2.join();
return 0;
}
3. 使用原子操作(Atomic Operations)
C++11引入了库,提供了原子类型,可以在不使用锁的情况下实现线程安全的操作。
示例代码:
#include
#include
#include
std::atomic<int> shared_variable(0);
void increment() {
++shared_variable; // 原子操作,无需锁
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Shared Variable: " << shared class="hljs-keyword">return 0;
}
4. 使用信号量(Semaphores)
虽然C++标准库没有直接支持信号量,但可以使用POSIX信号量或第三方库(如Boost)来实现。
使用POSIX信号量的示例:
#include
#include
#include
sem_t sem;
void worker() {
sem_wait(&sem); // 等待信号量
std::cout << "Worker thread is processing data.\n";
sem_post(&sem); // 释放信号量
}
int main() {
sem_init(&sem, 0, 1); // 初始化信号量,初始值为1
std::thread t1(worker);
std::thread t2(worker);
t1.join();
t2.join();
sem_destroy(&sem);
return 0;
}
5. 使用读写锁(Reader-Writer Locks)
当共享资源读取操作远多于写入操作时,使用读写锁可以提高并发性能。C++17引入了std::shared_mutex
。
示例代码:
#include
#include
#include
std::shared_mutex rw_mtx;
int shared_data = 0;
// 读取函数
void read_data() {
std::shared_lock lock(rw_mtx); // 共享锁
std::cout << "Read data: " << shared class="hljs-comment">// 写入函数
void write_data(int value) {
std::unique_lock lock(rw_mtx); // 独占锁
shared_data = value;
std::cout << "Write data: " << shared class="hljs-function">int main() {
std::thread t1(read_data);
std::thread t2(write_data, 42);
std::thread t3(read_data);
t1.join();
t2.join();
t3.join();
return 0;
}
6. 使用线程池和任务队列
为了更高效地管理线程和处理任务,可以使用线程池和任务队列。这可以减少线程创建和销毁的开销,并简化并发控制。
示例代码(使用C++11的std::queue
和std::mutex
实现简单的生产者-消费者模型):
#include
#include
#include
#include
#include
#include
class ThreadPool {
public:
ThreadPool(size_t threads) : stop(false) {
for(size_t i = 0; i < threads class="hljs-built_in">emplace_back([this](){
while(true){
std::function<void()> task;
{
std::unique_lock 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>
void enqueue(F&& f, Args&&... args) {
{
std::unique_lock lock(queue_mutex);
tasks.emplace([f, args...](){ f(args...); });
}
condition.notify_one();
}
~ThreadPool(){
{
std::unique_lock lock(queue_mutex);
stop = true;
}
condition.notify_all();
for(std::thread &worker: workers)
worker.join();
}
private:
std::vector workers;
std::queuevoid()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
int main(){
ThreadPool pool(4);
int task_num = 8;
for(int i = 0; i < task class="hljs-built_in">enqueue([i](){
std::cout << "Task "<< i class="hljs-string">" is running in thread " << std class="hljs-built_in">get_id() << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << "Task "<< i class="hljs-string">" completed.\n";
});
}
// 主线程可以继续执行其他任务或等待
return 0;
}
总结
在Linux环境下使用C++进行并发控制时,可以根据具体需求选择合适的同步机制:
- 互斥锁适用于保护共享资源,防止数据竞争。
- 条件变量用于线程间的协调和通信。
- 原子操作适用于简单的共享变量操作,无需锁。
- 信号量适用于更复杂的同步需求。
- 读写锁适用于读多写少的场景,提高并发性能。
- 线程池用于高效地管理线程和处理任务。
合理使用这些工具和方法,可以有效地实现线程安全和高效的并发控制。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权请联系我们,一经查实立即删除!