如何在Java中等待和通知在C / C ++中两个或多个线程之间的共享内存?我使用pthread库。
答案 0 :(得分:34)
您需要两个对象:互斥锁和条件变量,而不是您将用于等待/通知的Java对象。这些内容已使用pthread_mutex_init
和pthread_cond_init
初始化。
您将在Java对象上进行同步,请使用pthread_mutex_lock
和pthread_mutex_unlock
(请注意,在C中您必须手动配对这些对象)。如果您不需要等待/通知,只需锁定/解锁,那么您不需要条件变量,只需要互斥锁。请记住,互斥锁不一定是“递归的”,这意味着如果你已经持有锁,除非你设置init标志以表明你想要这种行为,否则你不能再拿它。
您呼叫java.lang.Object.wait
的地方,请致电pthread_cond_wait
或pthread_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的其他一些优势:
答案 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库有互斥,也可能适合你。