在现代软件开发中,多线程编程是提升应用程序性能和响应能力的重要手段。然而,多线程编程也带来了数据竞争和死锁等复杂问题。为了确保线程间的同步和共享数据的一致性,C++标准库提供了多种锁机制。
1. std::mutex
std::mutex
是最基础的互斥锁,用于保护共享数据,防止多个线程同时访问该数据。
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void print_thread_id(int id) {
mtx.lock();
std::cout << "Thread " << id << std::endl;
mtx.unlock();
}
int main() {
std::thread t1(print_thread_id, 1);
std::thread t2(print_thread_id, 2);
t1.join();
t2.join();
return 0;
}
在上述代码中,mtx.lock()
和mtx.unlock()
分别用于加锁和解锁,确保同一时刻只有一个线程可以访问临界区(std::cout
操作)。
2. std::recursive_mutex
std::recursive_mutex
允许同一线程多次获得同一锁,而不会导致死锁。适用于递归调用中需要加锁的场景。
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::recursive_mutex rec_mtx;
void recursive_function(int count) {
if (count <= 0) return;
rec_mtx.lock();
std::cout << "Count: " << count << std::endl;
recursive_function(count - 1);
rec_mtx.unlock();
}
int main() {
std::thread t(recursive_function, 5);
t.join();
return 0;
}
3. std::timed_mutex
std::timed_mutex
支持尝试在一定时间内获取锁。这在避免死锁和提高程序响应性方面很有用。
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
std::timed_mutex tmtx;
void try_lock_for_example() {
if (tmtx.try_lock_for(std::chrono::seconds(1))) {
std::cout << "Lock acquired" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
tmtx.unlock();
} else {
std::cout << "Failed to acquire lock" << std::endl;
}
}
int main() {
std::thread t1(try_lock_for_example);
std::thread t2(try_lock_for_example);
t1.join();
t2.join();
return 0;
}
4. std::recursive_timed_mutex
std::recursive_timed_mutex
结合了std::recursive_mutex
和std::timed_mutex
的特性
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
std::recursive_timed_mutex rtmtx;
void recursive_timed_function(int count) {
if (count <= 0) return;
if (rtmtx.try_lock_for(std::chrono::seconds(1))) {
std::cout << "Count: " << count << std::endl;
recursive_timed_function(count - 1);
rtmtx.unlock();
} else {
std::cout << "Failed to acquire lock" << std::endl;
}
}
int main() {
std::thread t(recursive_timed_function, 5);
t.join();
return 0;
}
5. std::shared_mutex
(C++17引入)
std::shared_mutex
允许多个线程同时读取共享数据,但只允许一个线程写入数据。这种机制适用于读多写少的场景。
cpp
#include <iostream>
#include <thread>
#include <shared_mutex>
std::shared_mutex smtx;
void read_function() {
smtx.lock_shared();
std::cout << "Reading data" << std::endl;
smtx.unlock_shared();
}
void write_function() {
smtx.lock();
std::cout << "Writing data" << std::endl;
smtx.unlock();
}
int main() {
std::thread t1(read_function);
std::thread t2(read_function);
std::thread t3(write_function);
t1.join();
t2.join();
t3.join();
return 0;
}
6. std::shared_timed_mutex
(C++14引入)
std::shared_timed_mutex
结合了std::shared_mutex
和std::timed_mutex
的特性。
cpp
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <chrono>
std::shared_timed_mutex stmtx;
void shared_timed_read_function() {
if (stmtx.try_lock_shared_for(std::chrono::seconds(1))) {
std::cout << "Reading data" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
stmtx.unlock_shared();
} else {
std::cout << "Failed to acquire shared lock" << std::endl;
}
}
void shared_timed_write_function() {
if (stmtx.try_lock_for(std::chrono::seconds(1))) {
std::cout << "Writing data" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(2));
stmtx.unlock();
} else {
std::cout << "Failed to acquire exclusive lock" << std::endl;
}
}
int main() {
std::thread t1(shared_timed_read_function);
std::thread t2(shared_timed_read_function);
std::thread t3(shared_timed_write_function);
t1.join();
t2.join();
t3.join();
return 0;
}
7. std::lock_guard
std::lock_guard
提供一种异常安全的方式来管理锁的生命周期,通常用于自动解锁。
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void lock_guard_example() {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Lock acquired using lock_guard" << std::endl;
// mtx is automatically unlocked when lock goes out of scope
}
int main() {
std::thread t(lock_guard_example);
t.join();
return 0;
}
8. std::unique_lock
std::unique_lock
比std::lock_guard
更加灵活,支持延迟加锁、解锁和重新加锁。
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
void unique_lock_example() {
std::unique_lock<std::mutex> lock(mtx);
std::cout << "Lock acquired using unique_lock" << std::endl;
lock.unlock();
std::cout << "Lock released" << std::endl;
lock.lock();
std::cout << "Lock reacquired" << std::endl;
}
int main() {
std::thread t(unique_lock_example);
t.join();
return 0;
}
9. std::shared_lock
(C++17引入)
std::shared_lock
用于管理共享互斥量(std::shared_mutex
或std::shared_timed_mutex
),提供了一种简单的方式来处理读锁。
cpp
#include <iostream>
#include <thread>
#include <shared_mutex>
std::shared_mutex smtx;
void shared_lock_example() {
std::shared_lock<std::shared_mutex> lock(smtx);
std::cout << "Shared lock acquired" << std::endl;
}
int main() {
std::thread t1(shared_lock_example);
std::thread t2(shared_lock_example);
t1.join();
t2.join();
return 0;
}
结论
C++标准库提供了多种锁机制,帮助开发者在多线程环境中确保数据的一致性和线程的同步。根据具体的应用场景选择合适的锁,可以有效地避免数据竞争和死锁问题,从而编写出高效、安全的多线程程序。