c++ - C ++:使用多个线程修改相同的指针
问题描述
我正在尝试处理图像的实验,其中我正在修改每个像素的颜色。我尝试使用“桶”来实现我的代码,其中我将图像划分为更小的区域——每个区域都接收一个专用线程来处理图像。
就我而言,我并不关心多个线程是否试图修改同一个资源,事实上,这似乎是重点。理论上,线程应该以像素的形式修改内存中的不同位置。然而,当打印我的结果时,似乎只有第一个任务会迭代 - 导致我认为某种竞争条件正在发生。
下面的函数管理每个任务的创建,并为其提供起始坐标和跨度以进行操作。我相信这工作正常,但它只是为了上下文:
Image*
CCManager::CCAsync(uint8_t bucketSize, Image* source,
const std::vector<float>& correction)
{
Image* newImg = new Image(); // This will contain our end result
newImg->resize(source->width(), source->height());
assert(buckets > 0);
// Now compute the width and height each bucket will render.
uint32_t width;
uint32_t height;
if(buckets == 2) // Each bucket takes a vertical rectangle
{
width = source->xSize()/2;
height = source->ySize();
}
else
{
// Set width and height to produce square grids (powers of 2)
// *** Not shown for Brevity ***
}
std::vector<std::thread> tasks; // The threads we are managing
// These coordinates will be fed as starting locations for each task
uint32_t startX = 0;
uint32_t startY = 0;
uint8_t tasksFinished = 0;
for(int i = 1; i <= buckets; ++i)
{
// Create a new task with a region for operation
tasks.emplace_back(std::thread(&CCManager::applyCCTask,this, startX, startY,
width, height, source, newImg, correction));
// No iteration is required for 1 bucket, simply paint the whole image
if(buckets == 1){break;}
// **** I REMOVED PART OF THE CODE THAT SHOWS WHERE EXPONENT
// IS DEFINED AND DETERMINED FOR BREVITY
// Reached last column, start a new row
if(i % exponent == 0)
{
startX = 0;
startY+= height;
}
// Keep incrementing horizontally
else
{
startX+= width;
}
}
while(tasksFinished < buckets)
{
// Join with whichever tasks finished
for(int i = 0; i < buckets; ++i)
{
if(tasks[i].joinable())
{
tasks[i].join();
tasksFinished++;
}
}
}
tasks.clear();
return newImg;
}
为每个任务提供了新的和源图像指针后,它们就开始起作用了。
下面的函数检索每个像素中的颜色,并调用一个相应地应用校正的方法。
void
CCManager::applyCCTask(uint32_t x, uint32_t y, uint32_t width, uint32_t height,
Image* source, Image* newImg,
const std::vector<float>& correction)
{
// ** THIS ACTUALLY PRINTS THE CORRECT COORDINATES AND REGION SPAN
// ** FOR EACH THREAD
printf("Task renders @ (%i,%i) with %i x %i box\n", x,y,width,height);
assert(source);
assert(newImg);
for (; x < width; ++x )
{
for (; y < height; ++y)
{
Byte4 pixel = source->pixel (x, y);
Color color = pixel.color;
printf("Before correction: Pixel(%i,%i) color [%i,%i,%i]\n",x,y, pixel.color[0], pixel.color[1], pixel.color[2]);
Color correctedColor= addCorrectionToColor( color, correction);
Byte4* newPixel= &newImg->pixel( x, y );
newPixel->color[0] = correctedColor[0];
newPixel->color[1] = correctedColor[1];
newPixel->color[2] = correctedColor[2];
printf("After correction: Pixel(%i,%i) color [%i,%i,%i]\n",x,y, newImg->pixel( x, y ).color[0], newImg->pixel( x, y ).color[1], newImg->pixel( x, y ).color[2]);
}
}
printf("Task Finished!\n");
}
使用显示的代码,所有任务最终都会打印带有其操作区域的起始消息,但在嵌套循环内,“之前”和“之后”消息似乎只从一个任务打印。
为什么我不允许从多个线程修改相同的图像,即使每个线程修改的实际像素数据不同?我是否可以避免在不添加诸如互斥锁之类的资源锁的情况下,这个实验的重点是让每个线程独立运行而不受任何阻碍。
解决方案
推荐阅读
- python - 这些代码块之间有什么不同?
- sql - 在 Range 中显示表格的输出
- asynchronous - 如何实现轮询异步 fn 的 Future 或 Stream?
- mysql - 在 mysql 5.7 中转换 rank() over (partition ....
- java - Google 应用引擎无法创建 DevAppServer
- javascript - NodeJS 从控制台获取 Promise 结果
- java - 如何在不同线程中执行两个接受同一类的可运行实例的方法?
- c# - 将视图模型传递给视图,将文本框中的数据保存到视图模型中,然后将该数据从视图模型传输到我的模型
- php - 如何让 PHP 调用 Ajax
- java - Android 10 创建文件夹 - getExternalFilesDir 改为 getExternalStorageDirectory()(已弃用)