好吧,實際上,我并不是要求執行緒必須“排隊”才能作業,但我只想通知多個執行緒。所以我不是在尋找障礙。
它有點像condition_variable::notify_all(),但我不希望執行緒被一個一個喚醒,這可能會導致饑餓(也是多個信號量后期操作中的潛在問題)。它有點像:
std::atomic_flag flag{ATOMIC_FLAG_INIT};
void example() {
if (!flag.test_and_set()) {
// this is the thread to do the job, and notify others
do_something();
notify_others(); // this is what I'm looking for
flag.clear();
} else {
// this is the waiting thread
wait_till_notification();
do_some_other_thing();
}
}
void runner() {
std::vector<std::threads>;
for (int i=0; i<10; i) {
threads.emplace_back([]() {
while(1) {
example();
}
});
}
// ...
}
那么我如何在 c/c 或 posix API 中做到這一點?
對不起,我沒有把這個問題說得足夠清楚,我會補充一些解釋。
我說的不是雷聲聽到的問題,是的,困擾我的是重新獲取鎖定,我嘗試過shared_mutex,仍然存在一些問題。
讓我將執行緒分成 2 個部分,1 個作為領導執行緒,執行寫入作業,其他作為作業執行緒,執行讀取作業。
但實際上它們在程式中都是平等的,領導執行緒是第一個訪問作業的執行緒(您可以將其視為該執行緒的共享緩沖區下溢)。作業完成后,只需要通知其他工人他們可以訪問。如果在mutex這里使用 ,任何執行緒都會阻塞其他執行緒。舉個例子:do_something()這里主執行緒的作業是a read,它阻塞了主執行緒,從而整個系統都被阻塞了。
不幸的是,shared_mutex不會解決這個問題:
if (!flag.test_and_set()) {
// leader thread:
lk.lock();
do_something();
lk.unlock();
flag.clear();
} else {
// worker thread
lk.shared_lock();
do_some_other_thing();
lk.shared_unlock();
}
在這段代碼中,如果領導作業已經完成,并且在這個unlock和下一個之間沒有太多事情要做lock(記住他們在一個回圈中),它可能會再次獲得鎖,讓工人作業不作業,這就是我稱之為它的原因starve早些時候。
and to explain the blocking in do_something(), I don't want this part of job takes all my CPU time, even if the leader's job is not ready (no data arrive for read)
and std::call_once may still not be the answer to this. because, as you can see, the workers must wait till the leader's job finished.
to summarize, this is actually a one-producer-multi-consumer problem. but I want the consumers can do the job when the product is ready for them. and any can be the producer or consumer. if any but the 1st find the product has run out, the thread should be the producer, thus others are automatically consumer.
but unfortunately, I'm not sure if this idea would work or not
uj5u.com熱心網友回復:
聽起來你正在尋找 call_once
#include <mutex>
void example()
{
static std::once_flag flag;
bool i_did_once = false;
std::call_once(flag, [&i_did_once]() mutable {
i_did_once = true;
do_something();
});
if(! i_did_once)
do_some_other_thing();
}
我不明白你的問題與饑餓有什么關系。您是否正在考慮雷鳴般的羊群問題?如果do_some_other_thing有互斥鎖,則可能會出現這種情況,但在這種情況下,您必須更詳細地描述您的問題。
uj5u.com熱心網友回復:
它有點像
condition_variable::notify_all(),但我不希望執行緒一一喚醒,這可能會導致饑餓
原則上不是喚醒被序列化,而是重新獲取鎖。
您可以通過std::condition_variable_any與 a 一起使用來避免這種情況,std::shared_lock只要沒有人在std::shared_mutex. 或者,您可以提供自己的Lockable型別。
但是請注意,這不會神奇地允許您同時運行多于內核數量的執行緒,或者強制調度程式啟動它們全部并行運行。它們只會被標記為可運行并正常調度 - 這只會修復您自己代碼中可避免的序列化。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/359447.html
標籤:c multithreading
上一篇:Firebase實時資料庫正在Unity3d中添加額外的結果元素
下一篇:Azure函式回傳唯一序列號
