Основываясь на previous question, мне было интересно, если следующий код будет работать, чтобы вычислить нижние и верхние границы для среднего значения свойства измеряются с помощью Atomics:Release Приобретать Семантику для вычисления нижнего и верхней границей Средней
std::atomic< unsigned int > m_accLower;
std::atomic< unsigned int > m_countLower;
std::atomic< unsigned int > m_accUpper;
std::atomic< unsigned int > m_countUpper;
// ...
void Class::UpdateLower(unsigned int delta)
{
m_countLower.fetch_add(1 , std::memory_order_relaxed);
m_accLower.fetch_add(delta , std::memory_order_release);
}
double Class::GetAverageLower()
{
auto acc = m_accLower.load(std::memory_order_acquire);
auto count = m_countLower.load(std::memory_order_relaxed);
return acc/(double)count;
}
void Class::UpdateUpper(unsigned int delta)
{
m_accUpper.fetch_add(delta , std::memory_order_relaxed);
m_countUpper.fetch_add(1 , std::memory_order_release);
}
double Class::GetAverageUpper()
{
auto count = m_countUpper.load(std::memory_order_acquire);
auto acc = m_accUpper.load(std::memory_order_relaxed);
return acc/(double)count;
}
Предположим, что нижнее и верхнее обновления всегда выдаются вместе, и одновременных обновлений нет.
Функция GetAverageLower()
гарантированно увидеть любые m_countLower
обновления, выпущенные перед обновлением он Seing в m_accLower
из-за расцепления приобретают на этом последнем поле, но, возможно, некоторые другие. Двойной случай встречается в GetAverageUpper()
.
Справедливо ли это? Гарантируется ли, что нижняя версия на самом деле всегда имеет нижнюю границу, а верхняя - верхняя граница среднего?
Если эти методы действительно делают то, что я ожидал, то фактическая средняя будет находиться в замкнутом интервале: [GetAverageLower() , GetAverageUpper()]
С таким переупорядочением 'm_accUpper' в конечном итоге будет« более обновлено », чем' m_countUpper', а затем 'inlinedValue' будет больше, чем в противном случае. Но это нормально! Это ожидаемое поведение, и это то, что я имел в виду, когда я суффикс этих элементов с помощью '* Upper' -' GetAverageUpper() 'разрешено возвращать значение, превышающее фактическое среднее значение, в то время как' GetAverageLower() 'может возвращать меньшее значение , – Tarc