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

时间:2010-01-18 11:10:34

标签: c++ c multithreading synchronization shared-memory

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

6 个答案:

答案 0 :(得分:34)

您需要两个对象:互斥锁和条件变量,而不是您将用于等待/通知的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之前设置一些条件,并在等待调用之后进行检查,并且需要在{a}中调用pthread_cond_wait环。与在Java中一样,在您等待时释放互斥锁。

与Java不同,除非您拿着显示器,否则无法呼叫notify可以实际调用pthread_cond_signal而无需持有互斥锁。但是,它通常不会获得任何东西,并且通常是一个非常糟糕的主意(因为通常你想要锁定 - 设置条件 - 信号 - 解锁)。因此,最好只是忽略它并将其视为Java。

没有更多的东西,基本模式与Java相同,而不是巧合。但是,请阅读所有这些功能的文档,因为您想知道和/或避免使用各种标记和有趣的行为。

在C ++中,您可以比使用pthreads API做得更好。您至少应该将RAII应用于互斥锁定/解锁,但是根据您可以使用的C ++库,您可能最好使用更多的C ++ - ish包装器来实现pthreads函数。

答案 1 :(得分:7)

在你的标题中,你将C和C ++混合在一起,随便进入“C / C ++”。我希望,你不是在编写一个混合了两者的程序。

如果你正在使用C ++ 11,你会发现一个可移植的(因为C ++,所以)更安全/更易于使用的替代pthreads(在POSIX系统上,它通常使用pthreads)。

您可以使用std::condition_variable + std::mutex进行等待/通知。 This example显示了:

#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. 此代码不包含单个原始指针(which are treacherous
  2. lambda expressions
  3. 各种其他syntactic swagg

答案 2 :(得分:6)

pthread_cond_wait和pthread_cond_signal可用于根据条件进行同步

答案 3 :(得分:4)

使用 Condition Variables 是一种方法:在Linux下使用pthread库时可以使用这些方法(参见链接)。

  

条件变量是变量   输入pthread_cond_t并与之一起使用   适当的等待功能   然后,继续处理。

答案 4 :(得分:2)

如果您不关心可移植性,Linux会提供eventfd,它可以为您提供所需的内容。每个eventfd都有一个内部计数器。在默认模式下,如果计数器为零,则从eventfd块中读取,否则立即返回。写入它将添加到内部计数器。

等待调用因此只是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));

答案 5 :(得分:1)

如果可用,您可以使用POSIX信号量。 pthread库有互斥,也可能适合你。