近期使用單生產者-多消費者模型是遇到乙個問題,曾經既然都沒有想到過。生產者執行緒的**例如以下。基本功能就是接收到乙個連線之後建立乙個socket物件並放到list中等待處理。
void datamanager::internalstart()
server_socket_->setsoblocking(true);
if (!server_socket_->listen())
socket *socket = null;
while (!stop_)
}}
多個消費者執行緒的的**例如以下,基本功能是從list中取得乙個socket物件進行處理。
void datamanager::workentry()
if (stop_)
break;
socket = socket_list_.front();
socket_list_.pop_front();
}bool success = false;do}
} while (success);
delete socket;
socket = null;
}}
執行過程中進場出現段錯誤,都是在12行(socket = socket_list_.front())。使用gdb除錯發現socket_list_
的size為0
。
增加以下的
log進行除錯
@@ -115,6 +115,7 @@ voiddatamanager::internalstart()
}@@ -129,11 +130,14 @@ voiddatamanager::workentry()
if (stop_)
break;
+ log(info) << "3: size: " << socket_list_.size();
socket = socket_list_.front();
socket_list_.pop_front();
+ log(info) << "4: size:" << socket_list_.size();
列印的log例如以下:
i0809 02:35:45.269896 17305datamanager.cc:114] recieved connection fd: 10.237.92.30:37220
i0809 02:35:45.269902 17305datamanager.cc:118] 1: size: 1i0809 02:35:45.269928 17310datamanager.cc:133] 2: size: 1
i0809 02:35:45.269935 17310datamanager.cc:137] 3: size: 1
i0809 02:35:45.269937 17310datamanager.cc:140] 4: size: 0
………i0809 02:35:45.271636 17305 datamanager.cc:114]recieved connection fd: 10.237.92.30:37224
i0809 02:35:45.271644 17305datamanager.cc:118] 1: size: 1
i0809 02:35:45.271663 17310datamanager.cc:137] 3: size: 1
i0809 02:35:45.271670 17310datamanager.cc:140] 4: size: 0
i0809 02:35:45.271739 17309 datamanager.cc:133]2: size: 0
i0809 02:35:45.271750 17309datamanager.cc:137] 3: size: 0
a) 正常的log順序
正常的log順序應該是,add乙個socket之後得到,有乙個消費者執行緒被signal喚醒並處理這個socket。
i0809 02:35:45.269902 17305datamanager.cc:118] 1: size: 1i0809 02:35:45.269928 17310datamanager.cc:133] 2: size: 1
i0809 02:35:45.269935 17310datamanager.cc:137] 3: size: 1
i0809 02:35:45.269937 17310datamanager.cc:140] 4: size: 0
b) 出錯時的log順序
出現錯誤時的log順序例如以下。
i0809 02:35:45.271644 17305datamanager.cc:118] 1: size: 1i0809 02:35:45.271663 17310datamanager.cc:137] 3: size: 1
i0809 02:35:45.271670 17310datamanager.cc:140] 4: size: 0
i0809 02:35:45.271739 17309 datamanager.cc:133]2: size: 0
i0809 02:35:45.271750 17309datamanager.cc:137] 3: size: 0
執行緒號能夠從第三列得出。 17305的執行緒是生產者執行緒,17310和17309為消費者執行緒。從列印的log能夠看除執行的順序例如以下:
a) 初始狀態;可是此時的socket_list_有變成空的了。 d) 17309得到socket_mu_。呼叫socket_list_.front()i. 17305:獲得socket_mu_準備向socket_list_中插入socket。
ii. 17309:正處於cond_var_.wait(&socket_mu_);狀態下等待cond_var發生。
iii. 17310 :socket_mu_應該是在試圖
b) 17305執行緒呼叫cond_var_.signal()喚醒17309。此時17309和17310還須要爭奪socket_mu_。應該是17310先得到了socket_mu_所以17309必須再次睡眠。
c) 17310將剛才17305生產的socket消耗了,而且釋放了socket_mu_。
時程式crash。
@@ -129,6 +129,9 @@ voiddatamanager::workentry()
if (stop_)
break;
單生產者 多消費者模型
問題出處 生產者消費者問題 有乙個生產者在生產產品,這些產品將提供給若干個消費者去消費,為了使生產者和消費者能併發執行,在兩者之間設定乙個有多個緩衝區的緩衝池,生產者將它生產的產品放入乙個緩衝區中,消費者可以從緩衝區中取走產品進行消費,所有生產者和消費者都是非同步方式執行的,但它們必須保持同步,即不...
生產者消費者模型二(單 多模型)
生產者 消費者問題 producer consumer 又名 有界緩衝區 bounded buffer 問題 單生產者 多消費者 設計要點 當緩衝區滿已滿,而此時生產者還想向緩衝區中放入乙個新的資料項時。則讓生產者睡眠,待消費者從緩衝區中取出乙個或多個資料項時再喚醒生產者。同樣的,當緩衝區滿已空,而...
生產者消費者問題之多生產者 單消費者模型
與單生產者和單消費者模型不同的是,多生產者 單消費者模型中可以允許多個生產者同時向產品庫中放入產品。所以除了保護產品庫在多個讀寫執行緒下互斥之外,還需要維護生產者放入產品的計數器,如下 include include include include include static const int ...