使用可变数量 std::thread 的引用问题
Problems with references using variable number of std::thread
我使用了 posix 线程 (pthread),但我正在尝试使用标准 C++11 线程(最有可能也是底层的 pthread)。我去过这里和其他论坛好几个 posts,但我无法弄清楚我的问题。如果有人能给我一盏灯,我会很高兴。
问题是我正在尝试将数据传递给线程,修改内部数据并且修改必须在抛出的线程完成(加入)后被主线程看到。问题是在某些线程中没有正确读取数据(int),因此输出结果不正确。
我可以编写的用于重现该问题的最少代码是:
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
void threadCallbackInt(int const & x)
{
int & y = const_cast<int &>(x);
y += 10;
std::cout<<"Inside Thread x = "<<y << " at position = " << &y <<std::endl;
}
int main(int argc, char* argv[])
{
unsigned int nthreads = 3;
vector<int> ints;
vector<std::thread> threads(nthreads);
threads.reserve(nthreads);
for(unsigned int i = 0; i < nthreads; i++){
ints.push_back(i);
std::cout<<"In Main Thread : Before Thread Start x = "<<ints.at(i)<< " at position = " << &ints.at(i) << std::endl;
threads[i] = std::thread(threadCallbackInt,std::ref(ints[i]));
}
cout << "size = " << threads.size() << endl;
for(unsigned int i = 0; i < nthreads; i++){
threads[i].join();
}
for(unsigned int i = 0; i < nthreads; i++){
std::cout<<"In Main Thread : After Thread Start x = "<<ints[i]<< " at position = " << &ints[i] << std::endl;
}
return 0;
}
在几个论坛上有几个类似的 post,但我认为最接近我的问题的是 C++ 11 std::thread strange behavior
注意我使用reserve方法是为了避免引用失效和编号失效,但是没有用。
根据执行情况,我得到不同的输出。这是输出之一:
In Main Thread : Before Thread Start x = 0 at position = 0x21d7c40
In Main Thread : Before Thread Start x = 1 at position = 0x21d81e4
In Main Thread : Before Thread Start x = 2 at position = 0x21d7c48
Inside Thread x = 10 at position = 0x21d81e4
size = 3
Inside Thread x = 12 at position = 0x21d7c48
Inside Thread x = 10 at position = 0x21d7c40
In Main Thread : After Thread Start x = 10 at position = 0x21d7c40
In Main Thread : After Thread Start x = 1 at position = 0x21d7c44
In Main Thread : After Thread Start x = 12 at position = 0x21d7c48
请注意,其中一个 x 仍未更新,即使在线程结束后也是如此。这是因为用于此的内存不正确(在线程之前是 0x21d81e4,在线程之后是 0x21d7c40)。如果您 运行 代码,您会看到结果会有所不同,并且任何时候引用不匹配,我都会得到错误的结果。
任何关于可能解决方案的信息都将非常受欢迎。抱歉,如果这个 post 重复(我找不到这个确切问题的实际答案)。但如果是,请注明原文post.
当 ints
被 ints.push_back(i);
调整大小时,引用 std::ref(ints[i])
无效。如果你想这样做,你还需要在 ints
上使用 reserve
。
在使用 gcc 进行测试时,
- 当
i == 0
时,则ints.capacity() == 1
- 当
i == 1
时,则ints.capacity() == 2
- 当
i == 2
时,则ints.capacity() == 4
这表明确实正在调整大小。
执行ints.push_back(i)后,a[0]的地址正在改变。
在打印 'In Main Thread...' 之前添加 std::cout << "ints.size()=" << ints.size() << " &ints[0]=" << &ints[0] << endl;
,输出如下(我正在使用 Visual Studio 2017 测试代码并添加 EnterCriticalSection/LeaveCriticalSection 以使输出不混淆。)
ints.size()=1 &ints[0]=0095BA28
In Main Thread : Before Thread Start x = 0 at position = 0095BA28
Inside Thread x = 10 at position = 0095BA28
ints.size()=2 &ints[0]=0095BA38
In Main Thread : Before Thread Start x = 1 at position = 0095BA3C
Inside Thread x = 11 at position = 0095BA3C
ints.size()=3 &ints[0]=0095E940
In Main Thread : Before Thread Start x = 2 at position = 0095E948
Inside Thread x = 12 at position = 0095E948
size = 3
In Main Thread : After Thread Start x = 10 at position = 0095E940
In Main Thread : After Thread Start x = 11 at position = 0095E944
In Main Thread : After Thread Start x = 12 at position = 0095E948
vector对象被调整大小,int[0]指向新分配的对象。
因此,添加 ints.reserve(nthreads);
会保留指向 ints 向量的指针。
ints.size()=1 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 0 at position = 00DD8608
Inside Thread x = 10 at position = 00DD8608
ints.size()=2 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 1 at position = 00DD860C
Inside Thread x = 11 at position = 00DD860C
ints.size()=3 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 2 at position = 00DD8610
Inside Thread x = 12 at position = 00DD8610
size = 3
In Main Thread : After Thread Start x = 10 at position = 00DD8608
In Main Thread : After Thread Start x = 11 at position = 00DD860C
In Main Thread : After Thread Start x = 12 at position = 00DD8610
我使用了 posix 线程 (pthread),但我正在尝试使用标准 C++11 线程(最有可能也是底层的 pthread)。我去过这里和其他论坛好几个 posts,但我无法弄清楚我的问题。如果有人能给我一盏灯,我会很高兴。
问题是我正在尝试将数据传递给线程,修改内部数据并且修改必须在抛出的线程完成(加入)后被主线程看到。问题是在某些线程中没有正确读取数据(int),因此输出结果不正确。
我可以编写的用于重现该问题的最少代码是:
#include <iostream>
#include <vector>
#include <thread>
using namespace std;
void threadCallbackInt(int const & x)
{
int & y = const_cast<int &>(x);
y += 10;
std::cout<<"Inside Thread x = "<<y << " at position = " << &y <<std::endl;
}
int main(int argc, char* argv[])
{
unsigned int nthreads = 3;
vector<int> ints;
vector<std::thread> threads(nthreads);
threads.reserve(nthreads);
for(unsigned int i = 0; i < nthreads; i++){
ints.push_back(i);
std::cout<<"In Main Thread : Before Thread Start x = "<<ints.at(i)<< " at position = " << &ints.at(i) << std::endl;
threads[i] = std::thread(threadCallbackInt,std::ref(ints[i]));
}
cout << "size = " << threads.size() << endl;
for(unsigned int i = 0; i < nthreads; i++){
threads[i].join();
}
for(unsigned int i = 0; i < nthreads; i++){
std::cout<<"In Main Thread : After Thread Start x = "<<ints[i]<< " at position = " << &ints[i] << std::endl;
}
return 0;
}
在几个论坛上有几个类似的 post,但我认为最接近我的问题的是 C++ 11 std::thread strange behavior
注意我使用reserve方法是为了避免引用失效和编号失效,但是没有用。
根据执行情况,我得到不同的输出。这是输出之一:
In Main Thread : Before Thread Start x = 0 at position = 0x21d7c40
In Main Thread : Before Thread Start x = 1 at position = 0x21d81e4
In Main Thread : Before Thread Start x = 2 at position = 0x21d7c48
Inside Thread x = 10 at position = 0x21d81e4
size = 3
Inside Thread x = 12 at position = 0x21d7c48
Inside Thread x = 10 at position = 0x21d7c40
In Main Thread : After Thread Start x = 10 at position = 0x21d7c40
In Main Thread : After Thread Start x = 1 at position = 0x21d7c44
In Main Thread : After Thread Start x = 12 at position = 0x21d7c48
请注意,其中一个 x 仍未更新,即使在线程结束后也是如此。这是因为用于此的内存不正确(在线程之前是 0x21d81e4,在线程之后是 0x21d7c40)。如果您 运行 代码,您会看到结果会有所不同,并且任何时候引用不匹配,我都会得到错误的结果。
任何关于可能解决方案的信息都将非常受欢迎。抱歉,如果这个 post 重复(我找不到这个确切问题的实际答案)。但如果是,请注明原文post.
当 ints
被 ints.push_back(i);
调整大小时,引用 std::ref(ints[i])
无效。如果你想这样做,你还需要在 ints
上使用 reserve
。
在使用 gcc 进行测试时,
- 当
i == 0
时,则ints.capacity() == 1
- 当
i == 1
时,则ints.capacity() == 2
- 当
i == 2
时,则ints.capacity() == 4
这表明确实正在调整大小。
执行ints.push_back(i)后,a[0]的地址正在改变。
在打印 'In Main Thread...' 之前添加 std::cout << "ints.size()=" << ints.size() << " &ints[0]=" << &ints[0] << endl;
,输出如下(我正在使用 Visual Studio 2017 测试代码并添加 EnterCriticalSection/LeaveCriticalSection 以使输出不混淆。)
ints.size()=1 &ints[0]=0095BA28
In Main Thread : Before Thread Start x = 0 at position = 0095BA28
Inside Thread x = 10 at position = 0095BA28
ints.size()=2 &ints[0]=0095BA38
In Main Thread : Before Thread Start x = 1 at position = 0095BA3C
Inside Thread x = 11 at position = 0095BA3C
ints.size()=3 &ints[0]=0095E940
In Main Thread : Before Thread Start x = 2 at position = 0095E948
Inside Thread x = 12 at position = 0095E948
size = 3
In Main Thread : After Thread Start x = 10 at position = 0095E940
In Main Thread : After Thread Start x = 11 at position = 0095E944
In Main Thread : After Thread Start x = 12 at position = 0095E948
vector对象被调整大小,int[0]指向新分配的对象。
因此,添加 ints.reserve(nthreads);
会保留指向 ints 向量的指针。
ints.size()=1 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 0 at position = 00DD8608
Inside Thread x = 10 at position = 00DD8608
ints.size()=2 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 1 at position = 00DD860C
Inside Thread x = 11 at position = 00DD860C
ints.size()=3 &ints[0]=00DD8608
In Main Thread : Before Thread Start x = 2 at position = 00DD8610
Inside Thread x = 12 at position = 00DD8610
size = 3
In Main Thread : After Thread Start x = 10 at position = 00DD8608
In Main Thread : After Thread Start x = 11 at position = 00DD860C
In Main Thread : After Thread Start x = 12 at position = 00DD8610