繁体   English   中英

在多线程环境中访问 map

[英]accessing to map in multithreaded environment

在我的应用程序中,多个线程需要访问 map object 以插入新项目或读取现有项目。 (没有“擦除”操作)。

线程使用此代码访问 map 元素:

struct PayLoad& ref = myMap[index];

我只是想知道我是否还需要将此代码块包装在互斥锁中? 或者不为此目的使用互斥锁是否安全?

谢谢。

由于至少有一个写操作,即插入,那么在访问map时需要有线程同步。 否则你有一个竞争条件

此外,返回对 map 中的值的引用不是线程安全的:

struct PayLoad& ref = myMap[index];

因为多个线程可以访问该值,并且其中至少一个可能涉及写入。 这也将导致竞争条件。 最好按值返回值,如下所示:

Payload GetPayload(int index)
{
    std::lock_guard<std::mutex> lock(mutex);
    return myMap[index];
}

所有线程都可以访问mutex

您的插入/写入操作还需要锁定相同的互斥锁:

void SetPayload(int index, Payload payload)
{
    std::lock_guard<std::mutex> lock(mutex);
    myMap[index] = std::move(payload);
}

TLDR:如果您将std::map用于您的数据,则无法保证 memory 分配。 每当您添加新元素/调整 map 的大小时,您应该期望元素被移动到其他 memory 位置,从而破坏任何没有互斥锁的多线程代码。


这条线本身很可能会被编译器优化掉,所以它真的取决于你之后对引用所做的事情。 您是从 map 元素中读取内容,还是将任何内容写回 memory?

即使在读取时,您也需要考虑其他线程在您的线程读取信息时写入数据,因此通常您总是希望使用某种互斥锁/同步机制来防止另一个线程写入您的 memory 即使您的线程是只能从中读取。

如果您可以保证 memory 在写入后不会更改,则无需互斥锁即可保存访问,但这假设:

  • 您不使用任何具有动态 memory 分配的容器
  • 当您读出时,您只读取保证完全初始化的元素(索引当前未在另一个线程上写入)
  • 没有任何有效载荷数据指向其他不受保护的动态 memory

如果没有看到更多的支持代码,就无法判断是否可以安全地做出这些假设。 到目前为止,您提供的所有内容,我都不鼓励省略互斥锁。


示例(理论上线程安全)

// Shared code
Payload myMap[32];   // Use c-style array to prevent dynamic memory allocation
int index = 0;
std::mutex mutex;

// Thread A (write)
// assumption: never wraps around or writes to old indices
// assumption: myMap[0] is initalized before Thread B is started
{
    std::lock_guard<std::mutex> guard(mutex);
    myMap[index + 1] = Payload(...);
    ++index;
}


// Thread B
{
    struct PayLoad& ref = myMap[index];
}

你看,我对这个例子做了很多假设。 破坏其中任何一个都可能破坏线程安全。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM