關(guān)于ACE_Task::last_thread()
在ACE應(yīng)用中,我們經(jīng)常用ACE_Task類實(shí)現(xiàn)多線程處理。由于ACE_Svc_Handler從ACE_Task派生,當(dāng)你寫的應(yīng)用程序使用了Acceptor-Connector框架同時(shí)又直接使用ACE_Task,如線程池,這時(shí)你會(huì)使用到ACE_Task。
因?yàn)樵S多ACE_Task對(duì)應(yīng)是動(dòng)態(tài)分配的,所以,必須在不再需要時(shí)把它們正確地釋放掉,知道何時(shí)可以釋放對(duì)象,這一點(diǎn)非常重要。C++NPv2第189頁(yè)描述了當(dāng)多線程涉及到的task對(duì)象在它們退出時(shí),使用ACE_Task::thr_count()方法確定正確釋放它們的方法。
在C++NPv2文檔中描述的過程并不不安全,這里有一個(gè)用例可以說明這一點(diǎn)。原因如下:
ACE在調(diào)用ACE_Task::close()掛鉤(hook)函數(shù)前檢查線程計(jì)數(shù)。
線程鎖(task thread)使控制線程計(jì)數(shù)順序化,所以不能通過調(diào)用ACE_Task::close()達(dá)到控制線程數(shù)這一目的,這是因?yàn)殛P(guān)閉掛勾(close hook)方法會(huì)刪除task 對(duì)象。因此,多個(gè)線程檢查ACE_Task:: thr_count()的值都為0是可能存在的。
舉例來說吧,我們假設(shè)這里有兩個(gè)線程,A和B,這給都要退出。線程A從svc()方法中退出控制,同時(shí),ACE開始線程記錄保護(hù)(record-keeping)。ACE獲得線程鎖并把活動(dòng)線程數(shù)從2減為1,接著,ACE釋放線程鎖并調(diào)用task的close()掛鉤方法。其間,線程B也從svc()方法中退出。在線程A檢查ACE_Task::thr_count()之前,ACE已執(zhí)行線程B的清楚操作可能導(dǎo)致task的線程計(jì)數(shù)器從1變?yōu)?.如果那樣,線程A和B都會(huì)看到線程計(jì)數(shù)器為0,并都試圖清理task對(duì)象。這一點(diǎn)肯定不是好事.......
發(fā)現(xiàn)并指出這一問題是一位長(zhǎng)時(shí)間使用ACE的用戶,Howard Finer,經(jīng)過一些迭代和試驗(yàn)Howard找到一個(gè)解決這一問題的辦法,即額外的維護(hù)線程計(jì)數(shù)器,記住到底是哪一個(gè)線程真實(shí)的把線程計(jì)數(shù)器從1變?yōu)?,(上述例子中的線程B)。這就要求ACE_Task增加一個(gè)新的方法 :
ACE_thread_t ACE_Task::last_thread (void) const
所以,在你的代碼實(shí)現(xiàn)ACE_Task::close()時(shí)需要包含如下的檢查
if (ACE_OS::thr_equal (ACE_Thread::self (),
?????????????????????? this->last_thread ()))
? {
??? // Do the cleanup here...
? }
這個(gè)方法可能會(huì)出現(xiàn)在ACE 5.5.2中。