Chinaunix
标题:
跪求多线程安全的智能指针实现~
[打印本页]
作者:
eagle518
时间:
2014-07-13 20:43
标题:
跪求多线程安全的智能指针实现~
本帖最后由 eagle518 于 2014-07-14 09:48 编辑
已知boost::shared_ptr如下验证多线程安全失败:
boost::shared_ptr<EString> g_shared_ptr(new EString("111"));
static void test_shared_ptr() {
{
boost::shared_ptr<EString> sx(new EString("x"));
boost::shared_ptr<EString> sy(new EString("y"));
sx = sy;
LOG("x=%s, y=%s", sx->c_str(), sy->c_str());
boost::shared_ptr<EString> sn;
// sx = null;
}
class spReader : public EThread {
public:
virtual void run() {
while (true) {
boost::shared_ptr<EString> local(g_shared_ptr);
LOG("s=%s", local->c_str());
}
}
};
class spWriter : public EThread {
public:
virtual void run() {
while (true) {
boost::shared_ptr<EString> newPtr(new EString("xxx"));
g_shared_ptr = newPtr;
}
}
};
EArray<EThread*> arr;
int i;
for (i = 0; i < 2; i++) {
spReader* sThread1 = new spReader();
sThread1->start();
arr.add(sThread1);
}
for (i = 0; i < 3; i++) {
spWriter* sThread2 = new spWriter();
sThread2->start();
arr.add(sThread2);
}
for (i = 0; i < arr.length(); i++) {
arr.getAt(i)->join(NULL);
}
}
请问有谁知道哪个开源智能指针实现是完全多线程安全的?
知道的请告知,不甚感激!
补充:lock-free实现更佳。
作者:
webdna
时间:
2014-07-13 21:56
帮顶
作者:
hellioncu
时间:
2014-07-14 08:34
本帖最后由 hellioncu 于 2014-07-14 08:35 编辑
这种情况下,我宁可不用智能指针
作者:
eagle518
时间:
2014-07-14 09:48
why?
回复
3#
hellioncu
作者:
hellioncu
时间:
2014-07-14 09:54
eagle518 发表于 2014-07-14 09:48
why? 回复 3# hellioncu
根据业务逻辑,创建者和释放者应该能明确,在统一的地方自己手工释放看着也清楚
作者:
eagle518
时间:
2014-07-14 10:05
可我现在的需求就是这样,我要实现仿JDK concurrent的类库,对象何时释放可以说是未知的。
回复
5#
hellioncu
作者:
shang2010
时间:
2014-07-14 10:22
java,好多人在用哈
作者:
eagle518
时间:
2014-07-14 10:58
对,而且java api文档很好很全。
我现在要实现的就是把jdk c++话,已实现更好的性能,同时又易用易学。
回复
7#
shang2010
作者:
egmkang
时间:
2014-07-14 17:49
你需要去补充操作系统知识!!!
任何一个对象,在同一个时刻,最多只能允许一个线程去写. 这是最起码的常识.
而std::atomic<int>这种给你的错觉就是, 你可以开多个线程去同时写, 但是实际上从微观的角度讲, 多个CPU内核还是串行的执行写操作, 这是一个必然的.
如果你的对象非常复杂, 没法做到std::atomic<int>这种支持原子写操作, 那么你就需要用到锁, 不管是mutex还是spin lock,本质上都是锁.
作者:
egmkang
时间:
2014-07-14 17:51
shared_ptr可以保证在多个线程间传递你的对象, 但是不能保证你自己那个对象的线程安全
shared_ptr的线程安全和你那个T类型的线程安全是两码事.
作者:
eagle518
时间:
2014-07-14 20:32
回复
9#
egmkang
不是无法实现多线程安全,参见:
http://stackoverflow.com/questio ... pointer-in-c-x86-64
当然,如果能lock-free实现更佳。
作者:
windoze
时间:
2014-07-14 21:24
你这么用当然没法做到线程安全了,shared_ptr的线程安全保障等级“等同于内置类型”。
你仔细体会一下。
作者:
eagle518
时间:
2014-07-14 23:29
回复
12#
windoze
我的需求是实现java一样的对象引用,如果上述实现不合理,还望不吝赐教。
作者:
windoze
时间:
2014-07-15 00:04
回复
13#
eagle518
内置类型的线程安全基本上是这样的:
1、多个线程同时读取同一个对象是安全的
2、多个线程同时读取和写入同一个对象是不安全的
也就是说,下面的代码是安全的:
int v=9527;
// thread 1 entry
void thread_func1() {
int sum=0
for(int i=0; i<100; i++) { sum+=v; }
}
// thread 2 entry
void thread_func2() {
int sum=0
for(int i=0; i<100; i++) { sum+=v*2; }
}
复制代码
下面的代码是不安全的
int v=9527;
// thread 1 entry
void thread_func1() {
int sum=0
for(int i=0; i<100; i++) { v=i; }
}
// thread 2 entry
void thread_func2() {
int sum=0
for(int i=0; i<100; i++) { sum+=v*2; }
}
复制代码
另外,shared_ptr本身就是一个“对象”。
综上所述,你再仔细体会一下
作者:
eagle518
时间:
2014-07-15 09:46
本帖最后由 eagle518 于 2014-07-15 09:47 编辑
回复
14#
windoze
内置类型线程安全我理解。
你能直接告诉我下面这段代码是否安全?若非安全,那问题会在哪里?
boost::shared_ptr<Object> ptr;
class Reader : public Thread {
virtual void Run {
for ( ; ; ) {
boost::shared_ptr<Object> local(boost::atomic_load(&ptr));
// do smth
}
}
};
class Writer : public Thread {
virtual void Run {
for ( ; ; ) {
boost::shared_ptr<Object> newPtr(new Object);
boost::atomic_store(&ptr, newPtr);
}
}
};
int main() {
Pool* pool = SystemThreadPool();
pool->Run(new Reader());
pool->Run(new Writer());
for ( ; ; )
}
##实测运行我未发现上面的代码存在异常。
作者:
windoze
时间:
2014-07-15 10:32
回复
15#
eagle518
我不能直接告诉你代码是否安全,你要自己体会。
如果你真的知道内置类型的线程安全,share_ptr你也应该能体会出来。
作者:
eagle518
时间:
2014-07-15 11:58
回复
16#
windoze
我感觉你的理解还是框框在std::shared_prt或boost::shared_ptr的线程安全模型上,
我需要的是多线程读写安全的智能指针实现,加锁实现也可以,
而不是讨论std::shared_prt或boost::shared_ptr的线程安全仅是等同内置类型线程安全。
作者:
windoze
时间:
2014-07-15 18:22
回复
17#
eagle518
你看这里有两个“对象”,一个是smart pointer(std/boost::shared_ptr或者GC pointer或者别的什么东西),另一个是这个smart pointer指向的对象。
你有没有搞清楚你到底要哪个对象的“线程安全”呢?
作者:
eagle518
时间:
2014-07-15 19:09
回复
18#
windoze
显然,我要的是两者同时安全。
作者:
windoze
时间:
2014-07-15 19:23
回复
19#
eagle518
如果你真需要“两者同时安全”,那显然你需要给两个对象都加锁。
不过,你需要“两者同时安全”的原因是什么你搞清楚了吗?
作者:
eagle518
时间:
2014-07-15 21:13
回复
20#
windoze
是的,需求很明确。
作者:
windoze
时间:
2014-07-15 22:01
回复
21#
eagle518
如果你需求很明确,那么解决方案也很明确——给smart pointer和它指向的对象各加一把锁。
作者:
eagle518
时间:
2014-07-16 00:21
回复
22#
windoze
晕,有没具体实现?
作者:
windoze
时间:
2014-07-16 09:25
回复
23#
eagle518
当然有拉,pthread_mutex_init/pthread_mutex_destroy/std::mutex/CreateEvent/CloseHandle,这不都是现成的?
作者:
egmkang
时间:
2014-07-16 17:53
eagle518 发表于 2014-07-14 20:32
回复 9# egmkang
你还是没能理解我说的话,旁边也有一位朋友说的,你得用一把锁.
shared_ptr就是一张纸, 你可以把这个纸看成透明的
比如
shared_ptr<string> str;
跟
string str;
在线程安全方面没有任何区别, 因为string并不支持并发写.
作者:
windoze
时间:
2014-07-16 19:03
回复
25#
egmkang
这个还是有点区别的,shared_ptr本身也不是线程安全的,你不能一边读一边写
同一个
shared_ptr对象。
作者:
eagle518
时间:
2014-07-17 10:55
本帖最后由 eagle518 于 2014-07-17 10:56 编辑
回复
26#
windoze
回复
25#
egmkang
我要的是具体实现,你们都理解错了。
讲原理我也懂,而且我自己前面就已经实现了一个,但是用了spinlock,实测发现性能不高,
所以抛出这个问题寻找良好实现的线索。
作者:
windoze
时间:
2014-07-17 17:43
回复
27#
eagle518
你就直说要现成的不就结了?
作者:
hello_wood
时间:
2014-07-17 17:53
有两种锁方案:shared_ptr类型共用一个锁,
或者每个被引用对象单独一个锁。
后者多了个锁对象管理。
要不就避免这种设计。
作者:
eagle518
时间:
2014-07-17 19:51
回复
28#
windoze
可以这样说,但我更喜欢推荐开源实现,如果您熟悉的话。
作者:
windoze
时间:
2014-07-17 21:51
回复
30#
eagle518
木有+字数补丁
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2