全局变量在多线程中内存相关问题
- 内存竞争:多个线程同时读写全局变量时,可能导致数据不一致。例如,一个线程读取全局变量
count
的值,另一个线程同时对 count
进行修改,可能使第一个线程读取到旧值或不一致的值。
- 数据一致性:由于缓存一致性问题,不同线程对全局变量的修改可能不会立即对其他线程可见,导致数据不一致。例如,线程A修改了全局变量
data
,但线程B由于缓存未更新,仍然读取到旧的 data
值。
局部变量在多线程中内存相关问题
- 内存竞争:局部变量一般每个线程都有自己的栈空间,所以本身不存在内存竞争问题。但如果局部变量是指向堆内存的指针,多个线程通过该指针访问堆内存时,可能产生内存竞争。例如,两个线程都通过同一个局部指针变量
ptr
访问堆上的同一块内存区域。
- 数据一致性:同样,对于局部变量本身,不存在数据一致性问题。但如果局部变量指向共享资源,如共享内存区域,也可能出现数据一致性问题,与全局变量类似。
解决方法及示例
- 互斥锁(
std::mutex
)
- 原理:互斥锁用于保护共享资源,同一时间只有一个线程能获取锁并访问共享资源。
- 示例:
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx;
int globalCount = 0;
void increment() {
for (int i = 0; i < 10000; ++i) {
mtx.lock();
++globalCount;
mtx.unlock();
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final globalCount: " << globalCount << std::endl;
return 0;
}
- 读写锁(
std::shared_mutex
)
- 原理:允许多个线程同时读共享资源,但只允许一个线程写。写操作时需要独占锁,读操作可以共享锁。
- 示例:
#include <iostream>
#include <thread>
#include <shared_mutex>
std::shared_mutex sharedMtx;
int sharedData = 0;
void read() {
sharedMtx.lock_shared();
std::cout << "Read data: " << sharedData << std::endl;
sharedMtx.unlock_shared();
}
void write() {
sharedMtx.lock();
++sharedData;
std::cout << "Write data: " << sharedData << std::endl;
sharedMtx.unlock();
}
int main() {
std::thread t1(read);
std::thread t2(write);
std::thread t3(read);
t1.join();
t2.join();
t3.join();
return 0;
}
- 条件变量(
std::condition_variable
)
- 原理:用于线程间的同步,一个线程等待某个条件满足,另一个线程满足条件后通知等待的线程。
- 示例:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lock(mtx);
while (!ready) cv.wait(lock);
std::cout << "thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> 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::cout << "10 threads ready to race...\n";
go();
for (auto& th : threads) th.join();
return 0;
}