简体   繁体   English

在多线程环境中访问 map

[英]accessing to map in multithreaded environment

In my application, multiple threads need to access to a map object for inserting new items or reading the existing items.在我的应用程序中,多个线程需要访问 map object 以插入新项目或读取现有项目。 (There is no 'erase' operation). (没有“擦除”操作)。

The threads uses this code for accessing map elements:线程使用此代码访问 map 元素:

struct PayLoad& ref = myMap[index];

I just want to know do I still need to wrap this block of this code inside of mutex?我只是想知道我是否还需要将此代码块包装在互斥锁中? Or is it safe to not using mutex for this purpose?或者不为此目的使用互斥锁是否安全?

Thanks.谢谢。

Since there is at least one write operation, ie an insert, then you need to have thread synchronization when accessing the map.由于至少有一个写操作,即插入,那么在访问map时需要有线程同步。 Otherwise you have a race condition .否则你有一个竞争条件

Also, returning a reference to the value in a map is not thread-safe:此外,返回对 map 中的值的引用不是线程安全的:

struct PayLoad& ref = myMap[index];

since multiple threads could access the value, and at least one of them could involve a write.因为多个线程可以访问该值,并且其中至少一个可能涉及写入。 That would also lead to a race condition.这也将导致竞争条件。 It is better to return the value by value like this:最好按值返回值,如下所示:

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

where mutex is accessible to all threads.所有线程都可以访问mutex

Your insert/write operation also needs to lock the same mutex:您的插入/写入操作还需要锁定相同的互斥锁:

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

TLDR: If you're using std::map for your data there are no guarantees about memory allocation. TLDR:如果您将std::map用于您的数据,则无法保证 memory 分配。 You should expect elements to be moved to other memory locations whenever you add new elements / resize the map, thus breaking any multi-threaded code without mutexes.每当您添加新元素/调整 map 的大小时,您应该期望元素被移动到其他 memory 位置,从而破坏任何没有互斥锁的多线程代码。


This line by itself will most likely be optimized away by the compiler, so it really depends on what you're doing with the reference afterwards.这条线本身很可能会被编译器优化掉,所以它真的取决于你之后对引用所做的事情。 Do you read from the map element or do you write anything back into memory?您是从 map 元素中读取内容,还是将任何内容写回 memory?

Even when reading you will need to account for other threads writing to the data while your thread reads out information, so generally you will always want to use some kind of mutex / synchronization mechanism to prevent another thread writing to your memory even if your thread is only reading from it.即使在读取时,您也需要考虑其他线程在您的线程读取信息时写入数据,因此通常您总是希望使用某种互斥锁/同步机制来防止另一个线程写入您的 memory 即使您的线程是只能从中读取。

If you can guarantee that the memory never changes after its been written, it is is save to access without mutex, but this assumes:如果您可以保证 memory 在写入后不会更改,则无需互斥锁即可保存访问,但这假设:

  • You do not use any container with dynamic memory allocation您不使用任何具有动态 memory 分配的容器
  • When you read out you only read elements that are guaranteed to be fully initialized (index is not currently being written to on another thread)当您读出时,您只读取保证完全初始化的元素(索引当前未在另一个线程上写入)
  • None of the payload data points to other un-guarded dynamic memory没有任何有效载荷数据指向其他不受保护的动态 memory

Without seeing more of your backing code it's impossible to tell whether those assumptions can safely be made.如果没有看到更多的支持代码,就无法判断是否可以安全地做出这些假设。 With everything you provided so far, I would discourage against leaving out mutexes.到目前为止,您提供的所有内容,我都不鼓励省略互斥锁。


Example (theoretically threadsafe)示例(理论上线程安全)

// 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];
}

You see, I made quite a few assumptions with this example.你看,我对这个例子做了很多假设。 Breaking any one of them could break thread safety.破坏其中任何一个都可能破坏线程安全。

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

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