Chinaunix
标题:
std::map并发时,只在写入的时候加锁,读到时候不加锁会有问题么?
[打印本页]
作者:
tesing2009
时间:
2013-10-24 14:22
标题:
std::map并发时,只在写入的时候加锁,读到时候不加锁会有问题么?
Hi,
小弟用到了std::map,但是为了提高多线程并发性,
不想加太多的锁,只在写入的时候加锁,读取的时候不加锁,
这样每次写入的进程只有一个,读取的进程有多个,在读取的时候会有问题么?
作者:
folklore
时间:
2013-10-24 14:25
有。。。。。。
作者:
linux_c_py_php
时间:
2013-10-24 14:26
只要有并发读写就会有问题, 这个很容易理解吧.
作者:
群雄逐鹿中原
时间:
2013-10-24 14:34
读的时候,正在写,肯定有问题
作者:
bruceteen
时间:
2013-10-24 14:38
BTW:C++11 有没有提供读写锁?
作者:
folklore
时间:
2013-10-24 14:45
回复
5#
bruceteen
c++ 不太可能提供一般意义上的锁及多线程支持, 原因你懂得~~
相对来说, 脚本语言以及像Java这样有VM的语言则对此毫无压力~~
作者:
bruceteen
时间:
2013-10-24 14:49
回复
6#
folklore
但 C++11 提供了多线程和锁的支持呀,我在mingw(gcc4.8.1)上用过
作者:
tesing2009
时间:
2013-10-24 15:04
回复
3#
linux_c_py_php
是的,但是现在业务处理的时间极短,每次都加锁则影响很大。大神,有啥好方法可以这次的加锁么。。多谢~
作者:
linux_c_py_php
时间:
2013-10-24 15:34
tesing2009 发表于 2013-10-24 15:04
回复 3# linux_c_py_php
方法当然有啊, 弄10个map, 每个map一把锁, 按照hash(key) % 10后选中对应map加锁操作.
作者:
tesing2009
时间:
2013-10-24 15:38
回复
9#
linux_c_py_php
是的,这时候可以增加10倍并发,但是我想把单个的map的锁也去掉。。。
作者:
tesing2009
时间:
2013-10-24 15:40
回复
6#
folklore
对于读写锁,写锁会阻塞后面的所有读么?
否则会因为读并发太多,读锁一直被占用,导致写锁永远获取不到的情况
作者:
folklore
时间:
2013-10-24 16:55
回复
7#
bruceteen
你是说parallel_for?
这种所谓的锁只是表面上的支持, 如果你要这么说, VC也“支持”。。。
锁和线程严重依赖于实现平台, 无法做为语言元素加入标准库的。。。
除非给库分等级,也就是说某个平台支持到某级的库为止。
作者:
folklore
时间:
2013-10-24 16:55
回复
11#
tesing2009
会。。。。
作者:
huangyacong
时间:
2013-10-24 16:59
俺记得在哪里看到vc的STL库写着线程安全的,可是,是真的吗?别被骗了,微软这个大坏蛋
作者:
folklore
时间:
2013-10-24 17:00
如果map某个锁成为性能瓶颈,
你只能自已实现数据结构,
尽量减小锁的粒度和占有时间。
减小占有时间的例子:
lock();
deleteitem(removeitem());
release();
复制代码
改为:
lock();
item it =removeitem())
release();
deleteitem(it);
复制代码
作者:
csumck
时间:
2013-10-24 17:09
回复
10#
tesing2009
可以想办法避免并发访问map。 不然不可能避免脏数据。
作者:
tesing2009
时间:
2013-10-24 18:24
回复
15#
folklore
好的,多谢回答 :)
作者:
tesing2009
时间:
2013-10-24 19:12
回复
15#
folklore
lock();
map<>::iterator itor = mpValue.find(szKey);
unlock();
//线程B写入mapValue
//线程A操作itor
复制代码
还有个问题请教下,如上代码,线程A在获取map的itor后,线程B对这个map进行写入,这时候线程A再访问这个itor,这个itor有可能失效么?
也就是说,加锁是应该包含线程A整个访问itor的的周期么?
虽然一般不会这样用,通常map直接保存key和对应的数据对象指针,然后直接操作这个数据对象了。没有深入到map里面看,不了解诶。。
作者:
folklore
时间:
2013-10-24 19:48
回复
18#
tesing2009
会失效, Map不支持访问计数。
但可以使用 std::SharedPtr做为Map元素来回避此问题。
作者:
tesing2009
时间:
2013-10-24 21:38
回复
19#
folklore
好的,多谢,我得多看点代码了。。
作者:
bruceteen
时间:
2013-10-25 08:33
回复
12#
folklore
不是 OpenMP、TBB、CUDA、OpenCL、MPI 等东西,C++11标准真的加入了线程支持。
我写个事例代码给你睇下,在MinGW(gcc4.8.1)上能编译运行
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
void foo( std::mutex& m )
{
//std::this_thread::sleep_for (chrono::seconds(1));
for( size_t i=0; i!=10; ++i )
{
std::lock_guard<std::mutex> lock(m);
cout << "ThreadID(" << std::this_thread::get_id() << "): " << i << endl;
}
}
int main()
{
std::mutex m;
thread t1( &foo, std::ref(m) );
thread t2( &foo, std::ref(m) );
t1.join();
t2.join();
return 0;
}
复制代码
一种可能的输出为
ThreadID(2): 0
ThreadID(3): 0
ThreadID(2): 1
ThreadID(3): 1
ThreadID(2): 2
ThreadID(3): 2
ThreadID(2): 3
ThreadID(3): 3
ThreadID(2): 4
ThreadID(3): 4
ThreadID(2): 5
ThreadID(3): 5
ThreadID(2): 6
ThreadID(3): 6
ThreadID(2): 7
ThreadID(3): 7
ThreadID(2): 8
ThreadID(3): 8
ThreadID(2): 9
ThreadID(3): 9
复制代码
作者:
windoze
时间:
2013-10-25 10:45
看这篇
http://erdani.com/publications/cuj-2004-12.pdf
读懂,然后自己实现一个。
作者:
folklore
时间:
2013-10-26 11:56
回复
21#
bruceteen
好, 我去试试看。
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2