在 C/C++ 共享内存中等待和通知
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2085511/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
wait and notify in C/C++ shared memory
提问by Sajad Bahmani
How to wait and notify like in Java In C/C++ for shared memory between two or more thread?I use pthread library.
如何像 Java 中的 C/C++ 一样等待和通知两个或多个线程之间的共享内存?我使用 pthread 库。
回答by Steve Jessop
Instead of the Java object that you would use to wait/notify, you need two objects: a mutex and a condition variable. These are initialized with pthread_mutex_init
and pthread_cond_init
.
您需要两个对象,而不是用于等待/通知的 Java 对象:一个互斥体和一个条件变量。这些用pthread_mutex_init
和初始化pthread_cond_init
。
Where you would have synchronized on the Java object, use pthread_mutex_lock
and pthread_mutex_unlock
(note that in C you have to pair these yourself manually). If you don't need to wait/notify, just lock/unlock, then you don't need the condition variable, just the mutex. Bear in mind that mutexes are not necessarily "recursive", This means that if you're already holding the lock, you can't take it again unless you set the init flag to say you want that behaviour.
在 Java 对象上同步的地方,使用pthread_mutex_lock
and pthread_mutex_unlock
(注意,在 C 中,您必须自己手动配对)。如果您不需要等待/通知,只需锁定/解锁,那么您不需要条件变量,只需要互斥锁。请记住,互斥体不一定是“递归的”,这意味着如果您已经持有锁,则不能再次使用它,除非您设置 init 标志来表示您想要这种行为。
Where you would have called java.lang.Object.wait
, call pthread_cond_wait
or pthread_cond_timedwait
.
你会打电话的地方java.lang.Object.wait
,打电话pthread_cond_wait
或pthread_cond_timedwait
。
Where you would have called java.lang.Object.notify
, call pthread_cond_signal
.
你会打电话的地方java.lang.Object.notify
,打电话pthread_cond_signal
。
Where you would have called java.lang.Object.notifyAll
, call pthread_cond_broadcast
.
你会打电话的地方java.lang.Object.notifyAll
,打电话pthread_cond_broadcast
。
As in Java, spurious wakeups are possible from the wait functions, so you need some condition which is set before the call to signal, and checked after the call to wait, and you need to call pthread_cond_wait
in a loop. As in Java, the mutex is released while you're waiting.
在 Java 中,等待函数可能会产生虚假唤醒,因此您需要在调用信号之前设置一些条件,并在调用等待之后检查,并且需要pthread_cond_wait
在循环中调用。就像在 Java 中一样,互斥锁在您等待时被释放。
Unlike Java, where you can't call notify
unless you hold the monitor, you canactually call pthread_cond_signal
without holding the mutex. It normally doesn't gain you anything, though, and is often a really bad idea (because normally you want to lock - set condition - signal - unlock). So it's best just to ignore it and treat it like Java.
不像Java,notify
除非你拿着监视器才能调用,你实际上可以在pthread_cond_signal
不拿着互斥锁的情况下调用。但是,它通常不会给您带来任何好处,并且通常是一个非常糟糕的主意(因为通常您想要锁定 - 设置条件 - 信号 - 解锁)。所以最好只是忽略它并像Java一样对待它。
There's not really much more to it, the basic pattern is the same as Java, and not by coincidence. Do read the documentation for all those functions, though, because there are various flags and funny behaviours that you want to know about and/or avoid.
没有更多的东西,基本模式与 Java 相同,并非巧合。不过,请阅读所有这些函数的文档,因为您想了解和/或避免各种标志和有趣的行为。
In C++ you can do a bit better than just using the pthreads API. You should at least apply RAII to the mutex lock/unlock, but depending what C++ libraries you can use, you might be better off using a more C++-ish wrapper for the pthreads functions.
在 C++ 中,您可以比仅使用 pthreads API 做得更好。您至少应该将 RAII 应用于互斥锁/解锁,但是根据您可以使用的 C++ 库,您最好为 pthreads 函数使用更多 C++ 风格的包装器。
回答by Domi
In your title, you blend C and C++ together so casually into "C/C++". I hope, you are not writing a program that is a mixture of the two.
在您的标题中,您将 C 和 C++ 随意地混合在一起,变成了“C/C++”。我希望,您编写的程序不是两者混合的。
If you are using C++11, you will find a portable and (because C++, so) much safer/easier-to-use alternative to pthreads (on POSIX systems, it usually uses pthreads under the hood though).
如果您使用的是 C++11,您会发现一个可移植的(因为 C++,所以)比 pthreads 更安全/更易于使用的替代品(在 POSIX 系统上,它通常在幕后使用 pthreads)。
You can use std::condition_variable
+ std::mutex
for wait/notify. This exampleshows how:
您可以使用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();
}
This code also highlights some other strengths that C++ has over C:
这段代码还突出了 C++ 相对于 C 的一些其他优势:
- this code does not contain a single raw pointer (which are treacherous)
- lambda expressions
- all kinds of other syntactic swagg.
- 此代码不包含单个原始指针(这是危险的)
- lambda 表达式
- 各种其他语法 swagg。
回答by jspcal
pthread_cond_wait and pthread_cond_signal can be used to synchronize based on a condition
pthread_cond_wait 和 pthread_cond_signal 可用于基于条件进行同步
回答by jldupont
Using Condition Variablesis one way to do it: those are available when using the pthread
library under Linux (see link).
使用条件变量是一种方法:pthread
在 Linux 下使用库时可以使用这些变量(请参阅链接)。
A condition variable is a variable of type pthread_cond_t and is used with the appropriate functions for waiting and later, process continuation.
条件变量是 pthread_cond_t 类型的变量,与适当的函数一起使用,用于等待和后续进程继续。
回答by Julian Stecklina
If you do not care about portability, Linux offers eventfd, which gives you exactly what you want. Each eventfd keeps an internal counter. In the default mode, reading from the eventfd blocks if the counter is zero, otherwise returns immediately. Writing to it will add to the internal counter.
如果您不关心可移植性,Linux 提供了 eventfd,它完全可以满足您的需求。每个 eventfd 都有一个内部计数器。在默认模式下,如果计数器为零,则从 eventfd 读取阻塞,否则立即返回。写入它会添加到内部计数器。
The wait call would thus just be a uint64_t buf_a; read(event_fd, &buf_a, sizeof(buf_a));
, where buf must be an 8-byte buffer. To notify the waiting thread, you would do uint64_t buf_b = 1; write(event_fd, &buf_b, sizeof(buf_b));
.
因此,等待调用将只是 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));
.
回答by user231967
If available, you might use POSIX semaphores. The pthread library has mutexes, which might work for you as well.
如果可用,您可以使用 POSIX 信号量。pthread 库具有互斥体,它也可能对您有用。