C ++映射的线程同步 [英] Thread synchronisation for C++ map

查看:132
本文介绍了C ++映射的线程同步的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用pthread(c ++ 98标准)创建一个多线程c ++程序。



我有一个std :: map可以访问多个线程。访问将添加和删除元素,使用find,以及使用[]运算符访问元素。



我理解,使用[]运算符读取,



第一个问题:我是否理解正确?



有些线程将通过[]访问元素,而其他线程将执行一些其他操作。显然我需要某种形式的线程同步。



我认为这应该工作的方式是:
- 虽然没有写操作正在做地图,线程应该能够同时读取它。
- 当线程想要写到映射时,它应该设置一个锁,所以没有线程开始任何读或写操作,然后它应该等待,直到所有读操作完成,此时它将执行操作并释放锁。
- 锁释放后,所有线程都应该能够自由读取。



主要的问题是:我可以使用什么线程同步方法这个行为?



我已经阅读过关于互斥,条件变量和信号量,就我所见,他们不会做我需要的东西。我熟悉互斥体,但不是cond。变量或信号量。



我看到的主要问题是,我需要一种方法锁定线程,直到某事发生(写操作结束),而没有那些线程然后锁定任何东西。
我还需要一个像一个反转的信号量,当计数器大于1时阻塞,然后在0时唤醒(即没有读操作)。



提前感谢。



PS这是我的第一篇文章。

解决方案


我知道使用 [] 运算符,甚至修改元素都是线程安全的,但其余的操作不是。



我能正确理解吗?


好吧,你说的不完全正确。并发读者可以使用 [] 访问 元素,或使用其他 const 函数(如 find size() ...) em>没有同时进行非 const 操作,例如 erase insert 修改 map<> 。并发线程可以修改不同的元素,但如果一个线程修改元素,则必须在另一个线程尝试访问或进一步修改该特定元素之前进行同步。


当线程想要写到映射时,它应该设置一个锁,所以没有线程开始任何读或写操作,然后它应该等到所有读操作已完成,此时它将执行操作并释放锁。 - 锁被释放后,所有线程都应该能够自由读取。


这不是很好的工作方式...为了写入者能够'等待所有读取操作完成,读取器需要获取锁定。

















b

我可以使用什么线程同步方法来实现这个行为?


互斥体确实是合适的,读取器 - 写入器锁(其允许并发读取器,一些还在其它读取器上的优先级等待写入器)的更高性能。相关的POSIX线程函数包括: pthread_rwlock_rdlock pthread_rwlock_wrlock pthread_rwlock_unlock 等。



为了比较两种方法,读者和作者使用互斥,你得到的序列化如下:



THREAD ACTION
reader1 pthread_mutex_lock(the_mutex)返回已获取的锁,
线程开始读取数据
reader2 pthread_mutex_lock(the_mutex )hangs,被reader1阻止
writer1 pthread_mutex_lock(the_mutex)挂起,被reader1阻止
reader1 pthread_mutex_unlock(the_mutex) - >释放锁
注意:一些系统保证reader2将在writer1之前解除阻塞,一些不
reader2被阻止pthread_mutex_lock(the_mutex)返回已获取锁,
和线程开始读取数据
reader1 pthread_mutex_lock(the_mutex)挂起,被reader2阻止
reader2 pthread_mutex_unlock(the_mutex) - >释放锁
writer1被阻止pthread_mutex_lock(the_mutex)返回已获取锁,
和线程开始写和/或读取数据
writer1 pthread_mutex_unlock(the_mutex) - >释放锁
reader1已阻止pthread_mutex_lock(the_mutex)返回获取锁,
和线程开始读取数据
... etc ...

使用读写锁,它可能更像这样(注意前两个读者同时运行):

  THREAD ACTION 
reader1 pthread_rwlock_rdlock(the_rwlock)返回已获取锁,
线程开始读取数据
reader2 pthread_rwlock_rdlock(the_rwlock)锁和
线程开始读取数据
writer1 pthread_rwlock_wrlock(the_rwlock)挂起,如被reader1 / 2禁止
reader1 pthread_rwlock_unlock(the_rwlock) - >释放锁
reader1 pthread_rwlock_rwlock(the_rwlock)挂起,作为挂起作者
reader2 pthread_rwlock_unlock(the_rwlock) - >释放锁
writer1已阻止pthread_rwlock_wrlock(the_rwlock)返回已获取锁,
和线程开始写入和/或读取数据
writer1 pthread_rwlock_unlock(the_rwlock) - >释放锁
reader1 blocked pthread_rwlock_rwlock(the_rwlock)返回已获取锁,
和线程开始读取数据
... etc ...


I'm creating a multithreaded c++ program using pthread (c++98 standard).

I have a std::map that multiple threads will access. The access will be adding and removing elements, using find, and also accessing elements using the [] operator.

I understand that reading using the [] operator, or even modifying the elements with it is thread safe, but the rest of the operations are not.

First question: do I understand this correctly?

Some threads will just access the elements via [], while others will do some of the other operations. Obviously I need some form of thread synchronisation.

The way I see this should work is: - While no "write" operation is being done to the map, threads should all be able to "read" from it concurrently. - When a thread wants to "write" to the map, it should set a lock so no thread starts any "read" or "write" operation, and then it should wait until all "read" operations have completed, at which point it would perform the operation and release the locks. - After the locks have been released, all threads should be able to read freely.

The main question is: what thread synchronisation methods can I use to achieve this behaviour?

I have read about mutex, conditional variables and semaphores, and as far as I can see they won't do excatly what I need. I'm familiar with mutex but not with cond. variables or semaphores.

The main problem I see is that I need a way of locking threads until something happens (the write operation ends) without those threads then locking anything in turn. Also I need something like an inverted semaphore, that blocks while the counter is more than 1 and then wakes when it is 0 (i.e. no read operation is being done).

Thanks in advance.

P.S. It's my first post. Kindly indicate if I'm doing something wrong!

解决方案

I understand that reading using the [] operator, or even modifying the elements with it is thread safe, but the rest of the operations are not.

Do I understand this correctly?

Well, what you've said isn't quite true. Concurrent readers can use [] to access existing elements, or use other const functions (like find, size()...) safely if there's no simultaneous non-const operations like erase or insert mutating the map<>. Concurrent threads can modify different elements, but if one thread modifies an element you must have some synchronisation before another thread attempts to access or further modify that specific element.

When a thread wants to "write" to the map, it should set a lock so no thread starts any "read" or "write" operation, and then it should wait until all "read" operations have completed, at which point it would perform the operation and release the locks. - After the locks have been released, all threads should be able to read freely.

That's not quite the way it works... for writers to be able to 'wait until all "read" operations have completed', the reader(s) need to acquire a lock. Writers then wait for that same lock to be released, and acquire it themselves to restrict other readers or writers until they've finished their update and release it.

what thread synchronisation methods can I use to achieve this behaviour?

A mutex is indeed suitable, though you will often get higher performance from a reader-writer lock (which allows concurrent readers, some also prioritorise waiting writers over further readers). Related POSIX threads functions include: pthread_rwlock_rdlock, pthread_rwlock_wrlock, pthread_rwlock_unlock etc..

To contrast the two approaches, with readers and writers using a mutex you get serialisation something like this:

THREAD   ACTION
reader1  pthread_mutex_lock(the_mutex) returns having acquired lock, and
         thread starts reading data
reader2  pthread_mutex_lock(the_mutex) "hangs", as blocked by reader1
writer1  pthread_mutex_lock(the_mutex) hangs, as blocked by reader1
reader1  pthread_mutex_unlock(the_mutex) -> releases lock
NOTE: some systems guarantee reader2 will unblock before writer1, some don't
reader2  blocked pthread_mutex_lock(the_mutex) returns having acquired lock,
         and thread starts reading data
reader1  pthread_mutex_lock(the_mutex) hangs, as blocked by reader2
reader2  pthread_mutex_unlock(the_mutex) -> releases lock    
writer1  blocked pthread_mutex_lock(the_mutex) returns having acquired lock,
         and thread starts writing and/or reading data
writer1  pthread_mutex_unlock(the_mutex) -> releases lock    
reader1  blocked pthread_mutex_lock(the_mutex) returns having acquired lock,
         and thread starts reading data
...etc...

With a read-write lock, it might be more like this (notice the first two readers run concurrently):

THREAD   ACTION
reader1  pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and
         thread starts reading data
reader2  pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and
         thread starts reading data
writer1  pthread_rwlock_wrlock(the_rwlock) hangs, as blocked by reader1/2
reader1  pthread_rwlock_unlock(the_rwlock) -> releases lock
reader1  pthread_rwlock_rwlock(the_rwlock) hangs, as pending writer
reader2  pthread_rwlock_unlock(the_rwlock) -> releases lock    
writer1  blocked pthread_rwlock_wrlock(the_rwlock) returns having acquired lock,
         and thread starts writing and/or reading data
writer1  pthread_rwlock_unlock(the_rwlock) -> releases lock    
reader1  blocked pthread_rwlock_rwlock(the_rwlock) returns having acquired lock,
         and thread starts reading data
...etc...

这篇关于C ++映射的线程同步的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆