簡體   English   中英

將兩個線程同步到同一計時器

[英]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_datadata_producer快,則相同的數據將被打印兩次。

如何防止這種行為? 換句話說,我希望在生產者有新數據之前,將print_data()阻塞。

另一方面,我不介意是否生成了數據並且沒有人打印它。 但我介意的生產日期被印不止一次?

我試圖將std::condition_variablestd::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM