C++映射的线程同步

Dan*_*Dan 8 c++ multithreading dictionary pthreads

我正在使用pthread(c ++ 98标准)创建一个多线程的c ++程序.

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

我知道使用[]运算符进行读取,甚至使用它修改元素是线程安全的,但其余操作则不是.

第一个问题:我能正确理解吗?

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

我认为这应该工作的方式是: - 虽然没有对地图进行"写入"操作,但线程应该能够同时"读取"它. - 当一个线程想要"写"到映射时,它应该设置一个锁,这样没有线程启动任何"读"或"写"操作,然后它应该等到所有"读"操作都完成,此时它将执行操作并释放锁. - 释放锁后,所有线程都应该能够自由读取.

主要问题是:我可以使用哪些线程同步方法来实现此行为?

我已经读过有关互斥,条件变量和信号量的内容,据我所知,他们不会做我需要的东西.我熟悉互斥,但不熟悉cond.变量或信号量.

我看到的主要问题是我需要一种锁定线程的方法,直到某些事情发生(写操作结束),然后这些线程依次锁定任何东西.此外,我需要类似倒置信号量的东西,当计数器大于1时阻塞,然后当它为0时唤醒(即没有进行读取操作).

提前致谢.

PS这是我的第一篇文章.请指出我做错了什么!

Ton*_*roy 6

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

我能正确理解吗?

那么,你所说的并不完全正确.并发读者可以使用[]访问现有元素,或安全地使用其他const函数(如find,size()...),如果没有同时非const操作,如eraseinsert不变map<>.并发线程可以修改不同的元素,但是如果一个线程修改了一个元素,则在另一个线程尝试访问或进一步修改该特定元素之前,必须先进行一些同步.

当一个线程想要"写"到地图时,它应该设置一个锁,这样没有线程启动任何"读"或"写"操作,然后它应该等到所有"读"操作都完成,此时它会执行操作并释放锁. - 释放锁后,所有线程都应该能够自由读取.

这不是它的工作方式......对于能够"等到所有"读取"操作已完成"的作者,读者需要获得锁定.编写者然后等待同一个锁被释放,并自己获取它以限制其他读者或作者,直到他们完成更新并释放它.

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

一个互斥锁确实是合适的,尽管你通常会从读写器锁中获得更高的性能(允许并发读者,有些还会优先考虑等待作者而不是其他读者).相关POSIX线程功能包括:pthread_rwlock_rdlock,pthread_rwlock_wrlock,pthread_rwlock_unlock等.

为了对比这两种方法,使用互斥锁的读者和编写者可以得到类似这样的序列化:

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...
Run Code Online (Sandbox Code Playgroud)

使用读写锁,可能更像是这样(注意前两个读取器并发运行):

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...
Run Code Online (Sandbox Code Playgroud)