真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

多線程下對象的析構(gòu)問題-創(chuàng)新互聯(lián)

多線程遇上對象析構(gòu)是個很麻煩的問題,這里我用一個多線程的單例模式去演示一下對象析構(gòu)的問題

創(chuàng)新互聯(lián)服務項目包括溫州網(wǎng)站建設、溫州網(wǎng)站制作、溫州網(wǎng)頁制作以及溫州網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,溫州網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到溫州省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

懶漢模式,加鎖,線程安全

懶漢模式:需要的時候new一個對象,不需要的時候delete

(線程安全的懶漢)單例模式的基本代碼示例:

class Message {
private:
	Message(){}
	Message(const Message&) = delete;
	Message& operator=(const Message&) = delete;
	~Message(){}

private:
	static Message* instance;//實例指針 
	//多線程下  多個線程,我們要給出互斥量
	static mutex _Mutex;
public:
	static Message* Get_instance();//獲取實例對象
	static void Del_instance();//刪除實例
};
Message* instance=nullptr;
mutex Message::_Mutex;

Message* Message::Get_instance()//獲得對象
{
	if (instance == nullptr)  //兩個if 多重判斷 減少一下鎖開銷
	{
		lock_guard_lock(_Mutex);//加鎖
		if (instance == nullptr)
		{
			instance = new Message();
		}
	}
	return instance;
}

void Message::Del_instance()//刪掉對象
{
	lock_guard_lock(_Mutex);//加鎖
	if (instance != nullptr)
	{
		delete instance;
		instance = nullptr;
	}
}

加入多線程的一些屬性

代碼如下:

class Message {
private:
	string message;//單例對象 a b c線程
	mutex _m_mutex;//有競爭 要互斥

	Message(){}
	Message(const Message&) = delete;
	Message& operator=(const Message&) = delete;
	~Message(){}

	void AddWordThread();//創(chuàng)建工作線程
private:
	static Message* instance;//實例指針 
	//多線程下  多個線程,我們要給出互斥量
	static mutex _Mutex;
	static void WordThread(Message* pm);//工作線程
public:
	static Message* Get_instance();//獲取實例對象
	static void Del_instance();//刪除實例

	void AddMess(const string& sm);//給此單例對象添加消息
};
Message* Message::instance=nullptr;
mutex Message::_Mutex;

Message* Message::Get_instance()//獲得對象
{
	if (instance == nullptr)  //兩個if 多重判斷 減少一下鎖開銷
	{
		lock_guard_lock(_Mutex);//加鎖
		if (instance == nullptr)
		{
			instance = new Message();
			instance->AddWordThread();
		}
	}
	return instance;
}

void Message::Del_instance()//刪掉對象
{
	lock_guard_lock(_Mutex);//加鎖
	if (instance != nullptr)
	{
		delete instance;
		instance = nullptr;
	}
}
void Message::AddMess(const string& sm)//多線程..添加消息
{
	lock_guard_lock(this->_m_mutex);//加的是當前對象指向的鎖
	//a線程輸入 b就不要輸入了
	message = sm;
}
void Message::AddWordThread()//創(chuàng)建線程
{
	thread m_th(&Message::WordThread,this);//創(chuàng)建了一個線程
	m_th.detach();//線程分離出去

}
void Message::WordThread(Message* pm)//工作線程
{
	for (;;)
	{
		lock_guard_lock(pm->_m_mutex);//保護的是消息
		cout<< "這是工作線程..."<< endl;
		if (!pm->message.empty())
		{
			cout<< pm->message<< endl;
			pm->message.clear();
		}
	}
}
void fun()
{
	Message* pa = Message::Get_instance();//獲得單例對象
	string sm[] = { "fun","fun_hello","fun_hhhh" };
	for (const auto& x : sm)
	{
		pa->AddMess(x);//添加消息
		//this_thread::sleep_for(chrono::milliseconds(100));
	}
	Message::Del_instance();//刪除單例對象
}
int main()
{
	fun();
	return 0;
}

這里的AddMess和WorkThread我沒有實現(xiàn)同步,只是說明一下當對象析構(gòu)之后,線程還在運行會有什么問題?
1、對象可能先于線程死亡,WorkThread就會進不去,什么也不執(zhí)行

每增添一個消息之后讓他睡眠個100毫秒看看,工作線程也多睡會讓他打印出來我們看看

void Message::WordThread(Message* pm)//工作線程
{
	for (;;)
	{
		lock_guard_lock(pm->_m_mutex);//保護的是消息
		cout<< "這是工作線程..."<< endl;
		if (!pm->message.empty())
		{
			cout<< pm->message<< endl;
			pm->message.clear();
		}
		this_thread::sleep_for(chrono::milliseconds(300));
	}
}
void fun()
{
	Message* pa = Message::Get_instance();//獲得單例對象
	string sm[] = { "fun","fun_hello","fun_hhhh" };
	for (const auto& x : sm)
	{
		pa->AddMess(x);//添加消息
		this_thread::sleep_for(chrono::milliseconds(100));
	}
	Message::Del_instance();//刪除單例對象
}

程序崩潰--->在打印完畢之后,懶漢模式創(chuàng)建的單例對象已經(jīng)被析構(gòu)了,但是工作線程里的pm已經(jīng)沒有資源了工作線程就會奔潰

????

如果要使他正常的話就得讓工作線程結(jié)束之后,單例對象析構(gòu)

解決方案:

讓判斷線程是否結(jié)束,如果結(jié)束了,線程join,給個bool類型stop用來判斷所有線程走完沒,走完了,修改析構(gòu)函數(shù)讓他為真,把線程對象至為空,當工作線程看到stop為真了,直接退出。

不過這么寫針對這個用例來說能走,不過要是再加個funa線程函數(shù),主線程一次走兩個,走多個就會出現(xiàn)問題了。

完美解決,引入shared_ptr和weak_ptr:要知道對于c++智能指針在多線程上面發(fā)揮巨大作用

還得了解一下,enable_shared_from_this 的使用

有關std::enable_shared_from_this_Oorik

class Message:public enable_shared_from_this//為了安全獲得當前this指針的智能指針
{
private:
	string message;//單例對象 a b c線程
	mutex _m_mutex;//有競爭 要互斥

	bool _stop;
	thread* pwth;//指向線程的指針
	Message():_stop(false),pwth(nullptr){}

	Message(const Message&) = delete;
	Message& operator=(const Message&) = delete;

	void AddWordThread();//創(chuàng)建工作線程	
public:

	~Message(){
		_stop = true;
		pwth->join();
		cout<< "工作線程結(jié)束.."<< endl;
		pwth = nullptr;
		cout<< "Message結(jié)束.."<< endl;
	}
private:
	//static Message* instance;//實例指針 
	static shared_ptrinstance;

	//多線程下  多個線程,我們要給出互斥量
	static mutex _Mutex;
	static void WordThread(weak_ptrpm);//工作線程
public:
	//static Message* Get_instance();//獲取實例對象
	static shared_ptrGet_instance();

	static void Del_instance();//刪除實例

	void AddMess(const string& sm);//給此單例對象添加消息
	void SetStop() { _stop = true; }
};
//Message* Message::instance=nullptr;
shared_ptrMessage::instance(nullptr);
mutex Message::_Mutex;

shared_ptrMessage::Get_instance()//獲得對象
{
	if (instance == nullptr)  //兩個if 多重判斷 減少一下鎖開銷
	{
		lock_guard_lock(_Mutex);//加鎖
		if (instance == nullptr)
		{
			//instance = new Message();
			instance = shared_ptr(new Message());
			instance->AddWordThread();
		}
	}
	return instance;
}

void Message::Del_instance()//刪掉對象
{
	lock_guard_lock(_Mutex);//加鎖
	if (instance != nullptr)
	{
		//delete instance;
		instance.reset();//當uses=0的時候 釋放資源
		//nstance = nullptr;
	}
}
void Message::AddMess(const string& sm)//多線程..添加消息
{
	lock_guard_lock(this->_m_mutex);//加的是當前對象指向的鎖
	//a線程輸入 b就不要輸入了
	message = sm;
}
void Message::AddWordThread()//創(chuàng)建線程
{
	//thread m_th(&Message::WordThread,this);//創(chuàng)建了一個線程
	//m_th.detach();//線程分離出去
	weak_ptrpa =shared_from_this();//獲取this擁有資源的ptr
	pwth = new thread(&Message::WordThread, pa);
}
void Message::WordThread(weak_ptrpm)//工作線程
{
	for (;;)
	{
		shared_ptrpa = pm.lock();
		if (!pa)return;
		lock_guard_lock(pa->_m_mutex);//保護的是消息
		//cout<< "這是工作線程..."<< endl;
		if (pa->_stop)
		{
			return;
		}
		if (!pa->message.empty())
		{
			cout<< pa->message<< endl;
			pa->message.clear();
		}
		//this_thread::sleep_for(chrono::milliseconds(300));
	}
}

void fun()
{
	shared_ptrpa = Message::Get_instance();//獲得單例對象
	string sm[] = { "fun","fun_hello","fun_hhhh" };
	for (const auto& x : sm)
	{
		pa->AddMess(x);//添加消息
		this_thread::sleep_for(chrono::milliseconds(1));
		//讓工作線程跑起來
	}
	Message::Del_instance();//刪除單例對象
}
void funa()
{
	shared_ptrpa = Message::Get_instance();//獲得單例對象
	string sm[] = { "funaa","funa_bb","funa_oo" };
	for (const auto& x : sm)
	{
		pa->AddMess(x);//添加消息
		this_thread::sleep_for(chrono::milliseconds(2000));
		//讓工作線程跑起來
	}
	Message::Del_instance();//刪除單例對象
}
int main()
{
	thread th(fun);
	
	thread tha(funa);
	th.join();
	tha.join();
	cout<< "main over"<< endl;
	return 0;
}

完事收工

你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


網(wǎng)站題目:多線程下對象的析構(gòu)問題-創(chuàng)新互聯(lián)
本文URL:http://weahome.cn/article/ceihgh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部