C ++映射的线程同步

时间:2015-06-17 10:40:55

标签: c++ multithreading dictionary pthreads

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

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

我理解使用[]运算符进行读取,或者甚至使用它修改元素是线程安全的,但其余的操作都不是。

第一个问题:我能理解这一点吗?

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

我认为这应该有效的方法是: - 虽然没有"写"正在对地图进行操作,线程应该都能够"读取"同时来自它。 - 当线程想要"写"到地图,它应该设置一个锁,所以没有线程启动任何"读"或"写"操作,然后它应该等到所有"读"操作已完成,此时它将执行操作并释放锁。 - 释放锁后,所有线程都应该能够自由读取。

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

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

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

提前致谢。

P.S。这是我的第一篇文章。请说明我是否做错了什么!

1 个答案:

答案 0 :(得分:6)

  

我理解使用[]运算符进行读取,或者甚至使用它修改元素是线程安全的,但其余的操作都不是。

     

我能理解这一点吗?

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

  

当线程想要&#34;写&#34;到地图,它应该设置一个锁,所以没有线程启动任何&#34;读&#34;或&#34;写&#34;操作,然后它应该等到所有&#34;读&#34;操作已完成,此时它将执行操作并释放锁。 - 释放锁后,所有线程都应该能够自由读取。

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

  

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

互斥锁确实是合适的,但是你通常会从读写器锁中获得更高的性能(允许并发读者,有些人还会优先考虑等待作者而不是其他读者)。相关的POSIX线程函数包括:pthread_rwlock_rdlockpthread_rwlock_wrlockpthread_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...