我是C ++中线程的新手。关于mutex
和lock_guard
的使用,我需要您的帮助(这部分并不重要)。我有一个主要功能和一个辅助功能。
请告诉我为什么多线程在添加lock_guard(mtx)
时不起作用;
当我删除它时,它运行得更快但是错误。你能帮帮我吗?
我需要正确访问向量vec
并启用线程。
#include <vector>
#include <thread>
std::mutex mtx;
void threadCall(std::vector<int> &vec, int start, int end){
std::lock_guard<std::mutex> guard(mtx);
for(int i=start; i<end; i++)
vec[i] = i;
}
void ThreadFunc(std::vector<int> vec){
std::vector<std::thread> threads(2);
threads[0] = std::thread(&threadCall, std::ref(vec), 0, 10);
threads[1] = std::thread(&threadCall, std::ref(vec), 10, 20);
threads[0].join();
threads[1].join();
}
int main(){
std::vector<int> vec(20);
ThreadFunc(vec);
return 0;
}
答案 0 :(得分:4)
互斥锁阻止线程并行执行任何工作。只要你能保证每个线程都不会写入向量的同一部分,你根本不需要互斥锁。
另一个问题是你按值传递矢量。您应该通过引用传递:
void threadCall(std::vector<int>& vec, int start, int end){
for(int i=start; i<end; i++)
vec[i] = i;
}
void ThreadFunc(std::vector<int>& vec){
std::vector<std::thread> threads(2);
threads[0] = std::thread(&threadCall, std::ref(vec), 0, 10);
threads[1] = std::thread(&threadCall, std::ref(vec), 10, 20);
threads[0].join();
threads[1].join();
}
int main(){
std::vector<int> vec(20);
ThreadFunc(vec);
}
答案 1 :(得分:4)
首先,停止按值传递向量,传递引用。在解决之后,您的特定示例实际上根本不需要互斥锁。您的矢量具有固定大小:
std::vector<int> vec(20);
所有元素都是默认构建的。因为你所做的就是任务:
vec[i] = i;
矢量不会重新分配任何存储空间或调整其项目数。因此,不需要锁定对整个向量的访问。结合每个线程在单独的子范围上操作的事实,并且不存在任何数据竞争。您不需要同步原语。
答案 2 :(得分:3)
问题是第一个线程占用互斥锁,第二个线程在释放之前无法工作。
因此,基本上您会收到一个多线程应用程序,其中所有线程都按顺序执行其工作。
你可以将你的守卫转移到for-loop
for(int i=start; i<end; i++) {
std::lock_guard<std::mutex> guard(mtx);
vec[i] = i;
}
这将使线程有可能在传递的向量上一起工作。
<强> BUT:强>
你需要考虑到多个线程并不总能提高性能,因为并发性!=并行性。
我希望以这种方式从这个应用程序实际上比单线程实现慢,因为以下内容:
mutex
相互阻塞,因此只有一个线程在时间运行解决方案IDEA:
如果你想真正并行运行它,你需要让线程处理独立数据,然后加入结果。