C++多线程服务器端编程(一)

线程安全 就是多个线程访问同一个对象时
多个线程访问同一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他操作,调用这个对象的行为都可以获得正确的结果,那么这个对象就是线程安全的。

1.1.3节中所谓一个线程安全的counter示例,每个counter对象有自己的mutex,因此不同的对象不构成锁争用lock contention
同时执行也没关系,只要他们不是访问同一个counter对象 ,也就是说不同对象他们是有各自的lock的, 但是另一种condition下,如果counter是动态创建的并通过指针来访问,前面的对象销毁时的race condition就还存在 ,因为指针访问的话就是同一个lock

1.2 对象的创建很简单
对象构造要做到线程安全 唯一的要求就是在构造期间不要泄露this指针
• 不要在构造函数中注册任何回调;
• 也不要在构造函数中把this 传给跨线程的对象;
• 即便在构造函数的最后一行也不行。

就是说在构造函数里的话它对象还没有完成初始化 如果他this被泄露给其他对象 别的线程就有可能访问这个半成品对象,不安全,不可取
可以接受的做法是 先构造 然后需要使用回调函数的话 用一个成员函数来定义 届时再去调用它即可

class Foo : public Observer
{
public:
Foo();
virtual void update();
// 另外定义一个函数,在构造之后执行回调函数的注册工作
void observe(Observable* s)
{
s->register_(this);
}
};
Foo* pFoo = new Foo;
Observable* s = getSubject();
pFoo->observe(s); // 二段式构造,或者直接写s->register_(pFoo);

1.3 销毁太难
mutex只能保证函数一个接一个执行

1.3.2 mutexlock只能用于同步本class的其他数据成员的读和写,它不能保护安全的析构
这是因为mutexlock成员的生命期最多与对象一样长,而析构动作可说是发生在对象身亡之后,在析构发生时锁已经被析构了

智能指针包括shared_ptr和unique_ptr两类

1.4 线程安全的observer
空悬指针 两个指针指向堆上的同一个对象 这两个指针位于不同的线程中,假设线程A通过指针1把对象销毁看 那2就成了空悬指针

要想安全的销毁指针 最好在别人都看不到的情况下 偷偷的做 (这正是垃圾回收的原理 所有人都用不到的东西一定是乐色啊XD)
好的解决方法:引用计数
把指针1和2都变成对象1和2,指向一个对象,这个对象再指向目标 现在中间对象有两个成员 指针和计数器
当指针析构掉 它的引用次数减少,知道引用次数变成0时,就可以安全的销毁了
这不就是引用计数型智能指针吗!!!

1.6 好使! shared_ptr/weak_ptr

shared_ptr控制对象的生命期
weak_ptr 不控制对象的生命期,但是他知道对象是否还活着
shared_ptr/weak_ptr是原子操作 不用锁

读写锁和互斥锁
读写锁:多个读者可以同时读 ;写者必须互斥;写者优先于读者
互斥锁:同一时间只有一个线程可以拥有互斥锁 其他线程必须等待

发布了44 篇原创文章 · 获赞 9 · 访问量 3380

猜你喜欢

转载自blog.csdn.net/puying1/article/details/100185473