[英]Synchronize two threads to the same timer
我有以下情況:
int main(){
data_t data;
std::thread data_producer([&data](){
while(true){
data = produce_data();
std::this_thread::sleep_for(1s);
}
});
auto print_data = [&data](){
std::cout << data.as_string() << "\n";
});
print_data();
//do some stuff
print_data();
print_data();
//do some stuff
print_data();
//.....
}
正如你看到的,數據生產者將永遠運行下去,試圖生產數據,每次覆蓋舊的。
當我調用print_data()
,最后生成的數據將被打印出來。 但是,如果print_data
比data_producer
快,則相同的數據將被打印兩次。
如何防止這種行為? 換句話說,我希望在生產者有新數據之前,將print_data()
阻塞。
另一方面,我不介意是否生成了數據並且沒有人打印它。 但我介意的生產日期被印不止一次?
我試圖將std::condition_variable
與std::mutex
。 我想出了這個解決方案。 我在某些情況下對其進行了測試,並且可以正常工作,但不確定是否正確:
int main(){
std::mutex m;
std::condition_variable cv;
bool ready{ false };
data_t data;
std::thread data_producer([&data](){
while(true){
{
std::lock_guard<std::mutex> lk(m);
data = produce_data();
ready = true;
}
cv.notify_one()
std::this_thread::sleep_for(1s);
}
});
auto print_data = [&data](){
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [&]{return ready;});
std::cout << data.as_string() << "\n";
ready = false;
});
print_data();
//do some stuff
print_data();
print_data();
//do some stuff
print_data();
//.....
}
盡管它按我在測試中所預期的那樣工作,但我高度懷疑我的解決方案是垃圾。
這是不是正確的方式?
這里給出的代碼存在很多問題。
您訪問data
的方式很容易導致並發問題。 您需要通過鎖保護變量的讀寫。 它似乎是堆棧上的結構。 但是,正如給定的那樣,您冒着以下風險:(1)在閱讀器中看到過時的值,因為運行閱讀器的CPU沒有關於編寫器所做操作的最新視圖(這是可見性問題)(2) date
值不完整或奇怪,因為編寫器在更新過程中停止了。 如果data
是大結構,則這是雙重事實,因為復制更有可能被中斷,而不僅僅是指針寫入,而指針寫入本身就是原子的。 但是您最終可能會看到構造中的對象不完整(有關更多詳細信息,請參見安全的初始化和發布 )。
對於您的主要問題,您要么需要保持制片人已經發布的內容的標簽。 您可能有一個計數器,該計數器在每次發布新數據時都會增加。 閱讀器還會存儲其最后打印的數據的計數器,並且僅在當前計數器較高時才打印數據。
該代碼可能類似於偽代碼:
mutex lock;
int counter = 0;
data_t data = null;
int last_saw = -1;
\\ in writer
data_t new_data = produce_data;
lock.acquire();
counter++;
data = new_data;
lock.release();
\\ in reader
data_t to_print = null;
lock.acquire();
if (counter > lastSaw) {
to_print = data;
last_saw = counter;
}
lock.release();
if (to_print != null)
count << to_print << endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.