多线程调用不同函数时如何仅锁定全局变量而非整个函数
如何仅锁定全局变量而非整个函数实现线程并发自增
我通过两个线程调用两个独立函数对全局变量进行自增操作,使用了std::lock_guard。但输出结果显示func1执行完成后func2才开始,呈现单线程运行的效果。请问如何仅锁定全局变量而非整个函数?
原代码
#include <iostream> #include <thread> #include <mutex> using namespace std; // 全局变量 int number; std::mutex myMutex; void func1(int interval) { std::lock_guard<std::mutex> lock (myMutex); for(int i = 0; i< interval; i++) { cout<<"thread one " << ++number<<std::endl; } } void func2(int interval) { std::lock_guard<std::mutex> lock (myMutex); for(int i = 0; i< interval; i++) { cout<<"thread two " << ++number<<std::endl; } } int main() { std::thread t1(func1, 1000); std::thread t2(func2, 1000); t1.join(); t2.join(); return 0; }
问题原因
你当前的代码把std::lock_guard放在了for循环外部,这意味着整个func1/func2函数执行期间都会持有互斥锁。当其中一个线程先获取锁后,另一个线程只能等待锁被释放才能开始运行,最终就表现为单线程串行执行的效果。
解决方法
将std::lock_guard移到for循环内部,让锁仅在操作共享资源(全局变量number和标准输出cout)的代码块生效,这样每次循环只会短暂持有锁,执行完自增和输出后立刻释放,两个线程就能交替获取锁并发执行:
修改后的代码:
#include <iostream> #include <thread> #include <mutex> using namespace std; // 全局变量 int number; std::mutex myMutex; void func1(int interval) { for(int i = 0; i< interval; i++) { std::lock_guard<std::mutex> lock (myMutex); cout<<"thread one " << ++number<<std::endl; } } void func2(int interval) { for(int i = 0; i< interval; i++) { std::lock_guard<std::mutex> lock (myMutex); cout<<"thread two " << ++number<<std::endl; } } int main() { std::thread t1(func1, 1000); std::thread t2(func2, 1000); t1.join(); t2.join(); return 0; }
补充说明
std::cout是全局共享资源,不加锁的话多个线程同时输出会导致打印内容错乱,所以必须把输出操作也包含在锁的保护范围内。std::lock_guard会在作用域结束时自动释放锁,放在循环内部的话,每次循环结束都会自动解锁,无需手动操作,保证了锁的正确释放。
内容的提问来源于stack exchange,提问作者gopinath bb
相关产品推荐
相关产品推荐

