我有多个线程同时调用push_back()共享对象std::vector.是std::vector线程安全的?或者我是否需要自己实现该机制以使其线程安全?
我想避免做额外的"锁定和释放"工作,因为我是图书馆用户而不是图书馆设计师.我希望寻找现有的矢量线程安全解决方案.怎么样boost::vector,这是从1.48.0以后新推出的.它是线程安全的吗?
假设我有一个N个元素的向量,但是这个向量的n个元素都有有意义的数据.一个更新程序线程更新第n个或第n + 1个元素(然后设置n = n + 1),还检查n是否太接近N并在必要时调用vector :: resize(N + M).更新后,线程调用多个子线程来读取第n个数据并进行一些计算.
保证子线程永远不会更改或删除数据(实际上没有数据被删除),updater在完成更新后会调用它们.
到目前为止还没有出现任何问题,但是我想问一下,如果从前一个更新中留下一些子工作线程,在将向量重新分配给更大的内存块时是否会出现问题.
或者在这样的多线程情况下使用向量是否安全,因为它不是线程安全的?
编辑:由于只有当updater调用vector :: resize(N + M,0)时才进行插入,我的问题是否有任何可能的解决方案?由于STL向量的巨大性能,我不愿意用可锁定的向量替换它,或者在这种情况下是否有任何高性能,已知和无锁向量?
我在多线程应用程序中使用std :: vector作为共享数据.我将线程封装在一个类中,例如,
class ABC {
public:
double a, b, c;
};
boost::mutex mutex1;
class XYZ {
public:
XYZ(vector<ABC> & pVector) {
ptrVector = &pVector;
m_thread = boost::thread(&XYZ::Start, this);
}
~XYZ() {}
void Start();
public:
vector<ABC> * ptrVector;
boost::thread m_thread;
};
void XYZ::Start() {
try {
while(1) {
boost::this_thread::interruption_point();
for (unsigned int i=0; i<ptrVector->size(); i++) {
{
boost::mutex::scoped_lock lock(mutex1);
ptrVector->at(i).a = double(rand())/10000;
ptrVector->at(i).b = double(rand())/10000;
ptrVector->at(i).c = double(rand())/10000;
}
}
}
}
catch(boost::thread_interrupted) {}
catch(std::exception) {}
}
Run Code Online (Sandbox Code Playgroud)
当我关闭应用程序时,有时候,在调试中会有2条错误消息, …
我制作了一个计算多核上素数的程序.(请忽略这样一个事实,即算法不是完全有效,数字0和1在这里被认为是素数.目的只是练习使用线程.)
该变量taken(下一个要测试的数字)在8个线程中共享.
问题是它可以通过一个线程递增,然后由另一个线程递增,当它已经增加两次(或更多次)时由它们读取,因此可以跳过某些值,这是一件坏事.
我认为它可以通过使用std::atomic_uint变量类型来解决,但我显然是错的.
有没有什么方法可以解决这个问题,而不需要使用,std::mutex因为我听说它会导致相当大的开销?源代码:
#include <iostream>
#include <chrono>
#include <vector>
#include <algorithm>
#include <thread>
#include <atomic>
int main()
{
const uint MAX = 1000;
std::vector<bool> isPrime(MAX), done(MAX);
std::fill(done.begin(), done.end(), false);
std::atomic_uint taken{0}; //shared variable
std::vector<std::thread> threads;
auto start = std::chrono::system_clock::now();
for (uint i = 0; i < 8; ++i) {
threads.emplace_back(
[&](){
bool res;
for (uint tested; (tested = taken.fetch_add(1)) < MAX; ) { //taken should be incremented and copied atomically
res = …Run Code Online (Sandbox Code Playgroud) 在性能关键的并行代码中,我有一个向量,其元素是:
目前,我预先计算了向量的所有可能值,因此竞争条件不应成为问题.为了提高性能,我正在考虑创建一个惰性向量,这样代码只在请求向量元素时执行计算.在并行区域中,可能会发生多个线程同时请求并且可能同时计算相同元素的情况.我如何处理这种可能的竞争条件?
下面是我想要实现的一个例子.它在Windows 10,Visual Studio 17下编译和运行.我使用C++ 17.
// Lazy.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <stdlib.h>
#include <chrono>
#include <math.h>
const double START_SUM = 1;
const double END_SUM = 1000;
//base object responsible for providing the values
class Evaluator
{
public:
Evaluator() {};
~Evaluator() {};
//Function with deterministic output, depending on the position
virtual double expensiveFunction(int pos) const = 0;
};
// …Run Code Online (Sandbox Code Playgroud) 当操作写入单个常量值时,您的代码中存在竞争条件是否有任何问题?例如,如果有一个并行循环seen为另一个数组中的每个值填充一个数组arr(假设没有越界索引的问题)。关键部分可能是以下代码:
//parallel body with index i
int val = arr[i];
seen[val] = true;
Run Code Online (Sandbox Code Playgroud)
由于写入的唯一值是true不需要互斥锁,并且可能对性能有害?即使线程互相踩踏,它们也会用相同的值填充地址,对吗?
我有一个下面的代码有时会出现分段错误?
vector<int> myvector;
void function1()
{
for(int i = 0;i<10;i++)
{
cout<<"writer thread:"<<i<<endl;
myvector.push_back(i);
}
}
void function2()
{
for(int i = 0;i<10;i++)
{
cout<<"reader thread:";
cout<<myvector[i]<<endl;
}
}
int main()
{
thread t1(function1);
thread t2(function2);
t1.join();
t2.join();
}
Run Code Online (Sandbox Code Playgroud)
我对一般容器和特别是向量的线程安全规则/保证有点困惑。我在一次采访中被问到这个问题,但没有说清楚为什么在线程中写入和在其他线程中写入不是线程安全操作。
在下面的向量 Push_back 链接中,我在数据争用部分看到“否则,不会访问任何现有元素,并且同时访问或修改它们是安全的”。该声明如何证明向量写入操作不是线程安全的?