簡體   English   中英

等待並在C / C ++共享內存中通知

[英]wait and notify in C/C++ shared memory

如何在Java中等待和通知在C / C ++中兩個或多個線程之間的共享內存?我使用pthread庫。

您需要兩個對象:互斥鎖和條件變量,而不是您將用於等待/通知的Java對象。 這些是使用pthread_mutex_initpthread_cond_init初始化的。

您將在Java對象上進行同步的位置,請使用pthread_mutex_lockpthread_mutex_unlock (請注意,在C中您必須手動將它們配對)。 如果您不需要等待/通知,只需鎖定/解鎖,那么您不需要條件變量,只需要互斥鎖。 請記住,互斥鎖不一定是“遞歸的”,這意味着如果您已經持有鎖,除非您將init標志設置為表示您想要該行為,否則不能再次使用它。

您將調用java.lang.Object.wait ,調用pthread_cond_waitpthread_cond_timedwait

你可以調用java.lang.Object.notify ,調用pthread_cond_signal

您將調用java.lang.Object.notifyAll ,調用pthread_cond_broadcast

與在Java中一樣,可以從等待函數中進行虛假喚醒,因此您需要在調用signal之前設置一些條件,並在調用wait之后進行檢查,並且需要在循環中調用pthread_cond_wait 與在Java中一樣,在您等待時釋放互斥鎖。

與Java不同,除非您持有監視器,否則無法調用notify ,您實際上可以在不保持互斥鎖的情況下調用pthread_cond_signal 但是,它通常不會獲得任何東西,並且通常是一個非常糟糕的主意(因為通常你想要鎖定 - 設置條件 - 信號 - 解鎖)。 所以最好只是忽略它並像Java一樣對待它。

它沒有更多的東西,基本模式與Java相同,而不是巧合。 但是,請閱讀所有這些功能的文檔,因為您需要了解和/或避免各種標記和有趣的行為。

在C ++中,您可以比使用pthreads API做得更好。 您至少應該將RAII應用於互斥鎖定/解鎖,但是根據您可以使用的C ++庫,您可能最好使用更多的C ++ - ish包裝器來實現pthreads功能。

在你的標題中,你將C和C ++混合在一起,隨便進入“C / C ++”。 我希望,你不是在寫一個兩者混合的程序。

如果你正在使用C ++ 11,你會發現一個可移植的(因為C ++,所以)更安全/更容易使用的替代pthreads(在POSIX系統上,它通常使用pthreads)。

您可以使用std::condition_variable + std::mutex進行wait / notify。 此示例顯示如何:

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex m;
std::condition_variable cv;
std::string data;
bool mainReady = false;
bool workerReader = false;

void worker_thread()
{
    // Wait until main() sends data
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return mainReady;});
    }

    std::cout << "Worker thread is processing data: " << data << std::endl;
    data += " after processing";

    // Send data back to main()
    {
        std::lock_guard<std::mutex> lk(m);
        workerReady = true;
        std::cout << "Worker thread signals data processing completed\n";
    }
    cv.notify_one();
}

int main()
{
    std::thread worker(worker_thread);

    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard<std::mutex> lk(m);
        mainReady = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();

    // wait for the worker
    {
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return workerReady;});
    }
    std::cout << "Back in main(), data = " << data << '\n';


    // wait until worker dies finishes execution
    worker.join();
}

此代碼還強調了C ++對C的一些其他優勢:

  1. 此代碼不包含單個原始指針( 它們是危險的
  2. lambda表達式
  3. 各種其他句法swagg

pthread_cond_wait和pthread_cond_signal可用於根據條件進行同步

使用Condition Variables是一種方法:在Linux下使用pthread庫時可以使用它們(參見鏈接)。

條件變量是pthread_cond_t類型的變量,並與適當的函數一起使用以等待和稍后的進程繼續。

如果您不關心可移植性,Linux會提供eventfd,它可以為您提供所需的內容。 每個eventfd都有一個內部計數器。 在默認模式下,如果計數器為零,則從eventfd塊中讀取,否則立即返回。 寫入它將添加到內部計數器。

等待調用因此只是一個uint64_t buf_a; read(event_fd, &buf_a, sizeof(buf_a)); uint64_t buf_a; read(event_fd, &buf_a, sizeof(buf_a)); ,其中buf必須是一個8字節的緩沖區。 要通知等待線程,你可以使用uint64_t buf_b = 1; write(event_fd, &buf_b, sizeof(buf_b)); uint64_t buf_b = 1; write(event_fd, &buf_b, sizeof(buf_b));

如果可用,您可以使用POSIX信號量。 pthread庫有互斥,也可能對你有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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