/ / C ++ 11, когато увеличавате атомната променлива, и я присвоите на друга стойност, това ли е атомна работа? - c ++, multithreading, c ++ 11, мутекс, атомен

C ++ 11, когато увеличавате атомната променлива, и я присвоите на друга стойност, това ли е атомна операция? - c ++, multithreading, c ++ 11, мутекс, атомен

аз съм объркан за атомната операция на C ++ 11,

Знам, че атомната променлива самостоятелно нарастване е атомна операция,

но аз използвам заданието на друга стойност, просто се съмнявам в него.

кодът точно като:

//....
static std::atomic<int> i; // global variable
//....
// in the thread
int id = ++i;

когато използвате заданието на различни нишки, е id уникалната стойност?

кода на изпитването:

#include <thread>
#include <mutex>
#include <atomic>
#include <iostream>

class A {
public:
static int idGenerator;
static std::mutex m;
A () {
// i know this operation will keep the id_ is unique
std::lock_guard<std::mutex> lock(m);
id_ = ++idGenerator;
}
void F(std::string name) {
std::cout << name << " " << id_ << std::endl;
}
private:
int id_;
};
int A::idGenerator = 0;
std::mutex A::m;

class B {
public:
static int idGenerator;
B () {
// after self increment, is the assignment atomic?
id_ = (++idGenerator);
}
void F(std::string name) {
std::cout << name << " " << id_.load() << std::endl;
}
private:
std::atomic<int> id_;
};
int B::idGenerator = 0;


void funcA() {
A a2;
a2.F("a2");
}

void funcB() {
B b2;
b2.F("b2");
}

int main() {
A a1;
B b1;
std::thread t1(&funcA);
std::thread t2(&funcB);
a1.F("a1");
b1.F("b1");

t1.join();
t2.join();
return 0;
}

има три нишки,

Класът, използващ lock_guard, запазва уникален характер.

Б клас просто използва атомна операция, и присвояване на променливата

Отговори:

8 за отговор № 1

Спецификацията на функциите за атомно увеличение дава решаваща представа за тяхното поведение - от http://en.cppreference.com/w/cpp/atomic/atomic/operator_arith за Интеграл T типа:

T operator++();
T operator++() volatile;
T operator++( int );
T operator++( int ) volatile;

Забележете, че връщат T по стойност и никога не връща обичайното T& от предварително увеличение. Поради тази причина "четенето" на пост-увеличената стойност не е втора отделна операция и е част от самата операция за атомно увеличение.

Вижте също текста "Връщана стойност" и "Забележка" на горепосочената страница.


2 за отговор № 2
static std::atomic<int> i; // global variable
// in the thread
int id = ++i;

когато използвате заданието на различни нишки, е id уникалната стойност?

Да. C ++ атомните променливи гарантират това ++i ще бъдат оценени атомно, така че всяка стойност от id върху различни нишки са уникални.

Изразът id = ++i; се изпълнява следните стъпки.

  1. атомно увеличение i, и под-израз (++i) се оценява след добавената стойност.
  2. задайте "оценена стойност" на id, (тази стъпка не е атомно)

0 за отговор № 3

kaka_ace,

За съжаление в случая, който сте предоставили, той не е атомен.

Тук е причината, поради която операцията преди увеличението е атомна, погледнете генерирания комплект:

 add %l0,1,%l0

(може да варира малко в зависимост от използвания монтаж)

Но това е операция.Това е защо тя е атомна.

Когато прехвърляте предварителна стъпка на местна променлива, това е най-малко две инструкции:

add %l0,1,%l0
st l0, [%fp-4]

Това генерира най-малко две инструкции и следователно вече не е атомна.

Моля, уведомете ни, ако имате въпроси!