什么是线程安全,如何保证线程安全?

什么是线程安全,如何保证线程安全?

线程安全

定义

线程安全(Thread Safety)是指多线程环境下,多个线程同时访问和操作同一资源时,程序的行为仍然是正确的,即不会因为多线程的并发操作而导致数据不一致或程序崩溃。

如何保证线程安全

确保线程安全通常涉及以下几种常见的方法和技术:

1. 互斥锁(Mutex)

互斥锁用于保证在同一时刻只有一个线程可以访问共享资源。

std::mutex: C++ 标准库中的互斥锁。std::lock_guard 和 std::unique_lock: 用于在作用域内自动管理互斥锁的加锁和解锁。

示例:

#include

#include

#include

std::mutex mtx;

int counter = 0;

void increment() {

std::lock_guard lock(mtx);

++counter;

}

int main() {

std::thread t1(increment);

std::thread t2(increment);

t1.join();

t2.join();

std::cout << "Counter: " << counter << std::endl;

return 0;

}

2. 读写锁(Read-Write Lock)

读写锁允许多个线程同时读取共享资源,但在写操作时,只有一个线程可以进行写操作,并且此时其他读操作和写操作都会被阻塞。

std::shared_mutex: C++17 引入的共享互斥锁。std::shared_lock: 用于管理读锁。

示例:

#include

#include

#include

std::shared_mutex rw_mtx;

int shared_data = 0;

void read() {

std::shared_lock lock(rw_mtx);

std::cout << "Read: " << shared_data << std::endl;

}

void write() {

std::unique_lock lock(rw_mtx);

shared_data++;

std::cout << "Write: " << shared_data << std::endl;

}

int main() {

std::thread t1(read);

std::thread t2(write);

t1.join();

t2.join();

return 0;

}

3. 原子操作(Atomic Operations)

原子操作提供了一种不用显式锁的线程安全操作方式,往往用于简单的计数器或标志位。

std::atomic: C++ 标准库中的原子类型和操作。

示例:

#include

#include

#include

std::atomic counter(0);

void increment() {

counter++;

}

int main() {

std::thread t1(increment);

std::thread t2(increment);

t1.join();

t2.join();

std::cout << "Counter: " << counter << std::endl;

return 0;

}

4. 条件变量(Condition Variable)

条件变量用于在线程间进行复杂的同步,通常和互斥锁一起使用。

std::condition_variable: C++ 标准库中的条件变量。

示例:

#include

#include

#include

#include

std::mutex mtx;

std::condition_variable cv;

bool ready = false;

void print_id(int id) {

std::unique_lock lock(mtx);

cv.wait(lock, [] { return ready; });

std::cout << "Thread " << id << std::endl;

}

void set_ready() {

std::lock_guard lock(mtx);

ready = true;

cv.notify_all();

}

int main() {

std::thread threads[10];

for (int i = 0; i < 10; ++i) {

threads[i] = std::thread(print_id, i);

}

std::this_thread::sleep_for(std::chrono::seconds(1));

set_ready();

for (auto& th : threads) {

th.join();

}

return 0;

}

5. 线程局部存储(Thread-Local Storage)

使用线程局部存储可以使每个线程拥有自己独立的变量副本,避免共享资源引起的竞争。

thread_local: C++11 引入的线程局部存储关键字。

示例:

#include

#include

thread_local int local_counter = 0;

void increment() {

local_counter++;

std::cout << "Local Counter: " << local_counter << std::endl;

}

int main() {

std::thread t1(increment);

std::thread t2(increment);

t1.join();

t2.join();

return 0;

}

相关推荐