前言:只能不断安慰自己好饭不怕晚!
悟性高是多么的重要啊!同样的起跑线,学的还是同样的东西,可不同的时间学,结果是不同的。
回归正题:
多线程通信、智能指针、muduo网络编程
智能指针完美的结局了多线程访问共享对象的线程安全问题。
前情提要:
#include <thread>
#include <iostream>
using namespace std;
class A
{
private:
/* data */
public:
A(/* args */);
void testA();
~A();
};
A::A(/* args */)
{
cout<<"A()"<<endl;
}
A::~A()
{
cout<<"~A()"<<endl;
}
void A::testA()
{
cout<<"非常好用的方法!"<<endl;
}
//子线程
void hander01(A* pw)
{
//子线程睡两秒
std::this_thread::sleep_for(std::chrono::seconds(2));
pw->testA(); //创建子线程访问A对象好用的方法
}
//mian线程
int main()
{
A *p = new A();
thread t1(hander01, p);
delete p;
p = nullptr;
return 0;
}
//输出结果是:
A()
~A()
非常好用的方法!
解释:这是非常不符合正常逻辑的,首先应该A对象生成,然后创建子线程,同时子线程睡两秒,主线程把A的对象析构,等子线程睡醒,居然还能输出A对象成员方法(输出:非常好用的方法!)。这是不符合逻辑的,A对象的方法应该在对象释放之前执行,如果说对象的空间度已经释放了,那么还能执行对象的方法吗?显然是不行的。
改进,使用智能指针,强弱指针,简单理解,在子线程调用的是强指针,那么子线程一定要访问对象,如果是弱指针,那么当对象空间已经释放了,子线程是不能访问对象的。
#include <thread>
#include <iostream>
using namespace std;
class A
{
private:
/* data */
public:
A(/* args */);
void testA();
~A();
};
A::A(/* args */)
{
cout<<"A()"<<endl;
}
A::~A()
{
cout<<"~A()"<<endl;
}
void A::testA()
{
cout<<"非常好用的方法!"<<endl;
}
//子线程 传入对象 弱智能指针
void hander01(weak_ptr<A> pw)
{
//睡了1秒之后访问析构对象的testA方法 是不合理的
//q访问A对象时, 需要监测A对象是否存活 这就是多线程访问共享对象的线程安全问题
//q->testA(); //创建子线程访问A对象好用的方法
shared_ptr<A> sp = pw.lock();
if(sp != nullptr){
sp->testA();
cout<<"sp不为空"<<endl;
}else{
cout<<"A对象已经析构,不能再访问!"<<endl;
}
}
//mian线程
int main()
{
{ //出作用域 变调用析构函数
shared_ptr< A> p (new A());
thread t1(hander01, weak_ptr<A> (p));
t1.detach();
//std::this_thread::sleep_for(std::chrono::seconds(2));
//如果打开,执行结果如下
//A()
//非常好用的方法!
//sp不为空
//~A()
}
//std::this_thread::sleep_for(std::chrono::seconds(1)); //主线程睡两秒
//阻塞等待子线程结束
//t1.join();
//std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
//输出结果
/*
A()
~A()
A对象已经析构,不能再访问!
*/
简单说明:指针对象会在作用域内创建并析构,如果把这段时间延长,那么子线程也能访问对象(相当于多线程共享资源),正常情况下,释放了对象空间,子线程再去访问对象,无法访问对象资源,会出现:A对象已经析构,不能再访问!