最近在看陈硕大大 的《Linux 多线程服务端编程:使用 muduo C++ 网络库》 ,看到里面用variadic template 和boost智能指针 实现了一个 signal/slot,现在C++11 已经把 boost的智能指针引入到标准库里边了。就想利用纯C++11 实现一遍。
结果发现,只要把原来代码中boost智能指针替换为c++11 的智能指针,把陈大大自己实现的MutexLock替换为std::mutex,
MutexLockGuard 替换为std::lock_guard 就可以了。
看来陈硕大大在很早以前就把握到了 C++ 的发展趋势啊。
在贴代码之前 ,先说几点。
一、
首先说一下shared_ptr<T>的线程安全性,它的线程安全性级别和std::string是一样的。它的计数操作是原子操作,但是多线程对它的并发读写是不安全的,因为他有两个操作,一个是修改地址一个是修改计数。可以想一下,现在有一个智能指针x指向一片内存,先对它读,比如y=x;,读一半(只修改了y的地址,但是计数还是1),此时再进行写操作,比如x=z,全部执行完,那么x指向z的内存,x原来指的内存因为计数减一被释放,这时再进行y=x读操作的另一半(计数加一),但是内存已经释放了。
所以多线程读写shared_ptr<T>需要保护临界区。
二、copyonwrite代替读写锁。
基本思想就是如果此刻有其他线程正在进行读操作,那么写操作需要在新的副本上执行。
实际上是这样的,每当进行读操作,则sp(shared_ptr简写)计数加一(计数至少为2)。这时如果有写操作,它先判断计数是否为1,若为1则没有线程读,可以在原内存上修改,若不为1,则复制内容到一片新内存并进行修改。其中写操作全程加锁保证只有一个线程可以写。
那么我们分析一下,若在写操作时有其他线程要进行读操作会等待锁释放;而没有写操作时可以有很多读操作,在进入和