我撰寫了這段代碼來演示僅使用 atomic 的二進制信號量。
1 個執行緒生產者最初將在佇列中推送 100 個元素。
稍后作為消費者的執行緒 2 和 3 將并行運行以使用此佇列。
問題是:我可以看到兩個執行緒列印相同的資料/元素
二進制信號量.cpp
std::queue<int> buffer;
int s_data = 1;
struct Semaphore
{
Semaphore():s_(1)
{
}
void wait()
{
while( s_.load() == 0); //you will keep waiting here until s_ becomes 1
s_.fetch_sub(1);
}
void signal()
{
s_.fetch_add(1);
}
private :
std::atomic<int> s_ ;
};
Semaphore s;
void producer()
{
while(s_data <= 100)
{
s.wait();
// critical section starts
{
std::ostringstream oss;
oss << "Consumer pushing data " << s_data <<endl;
cout << oss.str();
buffer.push(s_data );
}
// critical section ends
s.signal();
}
}
void consumer()
{
while (1)
{
s.wait();
// critical section starts
if (!buffer.empty())
{
int top = buffer.front();
buffer.pop();
std::ostringstream oss;
oss << "consumer thread id= " << this_thread::get_id() << " reading data = " << top << endl;
cout << oss.str();
}
// critical section ends
s.signal();
}
}
int main()
{
Semaphore s;
std::thread prod(producer);
prod.join();
std::thread cons1(consumer);
std::thread cons2(consumer);
cons1.join();
cons2.join();
}
uj5u.com熱心網友回復:
如果您需要對原子執行更多操作,則需要檢查資料是否未更改的一致性。否則,您將在其他答案中指出“差距”。
有一個compare_exchange應該用于:
void wait()
{
auto oldValue = s_.load();
while (oldValue == 0 || !s_.compare_exchange_strong(oldValue, oldValue - 1))
oldValue = s_.load();
}
現在將更新是否oldValue
過期并執行新的檢查(回圈的新迭代),并在下一次迭代條件下再次檢查。oldValue
uj5u.com熱心網友回復:
你有一個等待的“差距”:
void wait()
{
while( s_.load() == 0); //you will keep waiting here until s_ becomes 1
s_.fetch_sub(1);
}
load() 和 fetch_sub 本身是原子的,但是在 while... load() 和 fetch_sub() 之間存在差距。也許您應該使用“交換”(并評估結果):https : //en.cppreference.com/w/cpp/atomic/atomic/exchange 或者更好地使用 compare_exchange:https ://en.cppreference.com/w /cpp/原子/原子/compare_exchange
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/444262.html