在 C/C 共享内存中等待并通知

新手上路,请多包涵

如何在 C/C++ 中的 Java 中等待和通知两个或多个线程之间的共享内存?我使用 pthread 库。

原文由 Sajad Bahmani 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.1k
2 个回答

您需要两个对象,而不是用于等待/通知的 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 中一样,等待函数可能会产生虚假唤醒,因此您需要在调用信号之前设置一些条件,并在调用等待之后检查,并且您需要在循环中调用 pthread_cond_wait .与在 Java 中一样,互斥锁在您等待时被释放。

与 Java 不同,您不能调用 notify 除非您持有监视器,您实际上 可以 调用 pthread_cond_signal 而不持有互斥锁。但是,它通常不会为您带来任何好处,而且通常是一个非常糟糕的主意(因为通常您想要锁定 - 设置条件 - 信号 - 解锁)。所以最好只是忽略它,像 Java 一样对待它。

没有更多的东西,基本模式与 Java 相同,并非巧合。不过,请阅读所有这些功能的文档,因为您想了解和/或避免各种标志和有趣的行为。

在 C++ 中,您可以比仅使用 pthreads API 做得更好。您至少应该将 RAII 应用于互斥锁/解锁,但根据您可以使用的 C++ 库,您最好为 pthreads 函数使用更 C++ 的包装器。

原文由 Steve Jessop 发布,翻译遵循 CC BY-SA 3.0 许可协议

在您的标题中,您将 C 和 C++ 如此随意地混合为“C/C++”。我希望,您编写的程序不是两者的混合体。

如果您使用的是 C++11,您会发现 pthreads 的可移植替代品(在 POSIX 系统上,它通常在底层使用 pthreads)。

您可以使用 std::condition_variable + std::mutex 等待/通知。 这个例子 展示了如何:

 #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();
}

原文由 Domi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题