我正在使用pthread(c ++ 98标准)创建多线程c ++程序。
我有一个多线程可以访问的std :: map。访问将使用find添加和删除元素,并使用[]运算符访问元素。
我理解使用[]运算符进行读取,或者甚至使用它修改元素是线程安全的,但其余的操作都不是。
第一个问题:我能理解这一点吗?
有些线程只会通过[]访问元素,而其他线程则会执行其他一些操作。显然我需要某种形式的线程同步。
我认为这应该有效的方法是: - 虽然没有"写"正在对地图进行操作,线程应该都能够"读取"同时来自它。 - 当线程想要"写"到地图,它应该设置一个锁,所以没有线程启动任何"读"或"写"操作,然后它应该等到所有"读"操作已完成,此时它将执行操作并释放锁。 - 释放锁后,所有线程都应该能够自由读取。
主要问题是:我可以使用哪些线程同步方法来实现此行为?
我已经阅读了有关互斥锁,条件变量和信号量的内容,据我所知,他们不会做出我需要的东西。我熟悉互斥,但不熟悉cond。变量或信号量。
我看到的主要问题是我需要一种锁定线程的方法,直到某些事情发生(写操作结束),然后这些线程依次锁定任何东西。 此外,我需要一个类似倒置信号量的东西,当计数器大于1时会阻塞,然后在它为0时唤醒(即没有进行读取操作)。
提前致谢。
P.S。这是我的第一篇文章。请说明我是否做错了什么!
答案 0 :(得分:6)
我理解使用
[]
运算符进行读取,或者甚至使用它修改元素是线程安全的,但其余的操作都不是。我能理解这一点吗?
嗯,你所说的并不是真的。并发读者可以使用[]
访问 现有 元素,或使用其他const
函数(例如find
,size()
...)安全如果没有同时非const
操作,例如erase
或insert
变异map<>
。并发线程可以修改不同的元素,但是如果一个线程修改了一个元素,则在另一个线程尝试访问或进一步修改该特定元素之前,必须先进行一些同步。
当线程想要&#34;写&#34;到地图,它应该设置一个锁,所以没有线程启动任何&#34;读&#34;或&#34;写&#34;操作,然后它应该等到所有&#34;读&#34;操作已完成,此时它将执行操作并释放锁。 - 释放锁后,所有线程都应该能够自由读取。
这不是它的工作方式......作家能够等到所有&#34;读&#34;操作已经完成&#39; ,读者需要获得锁定。作家然后等待同一个锁被释放,并自己获取它以限制其他读者或作者,直到他们完成更新并释放它。
我可以用什么线程同步方法来实现这种行为?
互斥锁确实是合适的,但是你通常会从读写器锁中获得更高的性能(允许并发读者,有些人还会优先考虑等待作者而不是其他读者)。相关的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...
使用读写锁定,可能更像是这样(注意前两个读取器并发运行):
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...