Но что мне делать, чтобы синхронизировать статическое поле tmp, когда есть несколько потоков, в которых можно инициализировать объект.
Вы должны использовать std::atomic<unsigned>
для счетчика, чтобы сделать приращениеэто потокобезопасно.unsigned
, чтобы гарантировать, что оборачивание счетчика не приведет к неопределенному поведению.
class Object {
static std::atomic<unsigned> tmp;
public:
unsigned const id = tmp.fetch_add(1, std::memory_order_relaxed);
};
std::atomic<unsigned> Object::tmp{0};
Обратите внимание, что инициализация Object::tmp
происходит на статической фазе инициализации перед динамикой инициализация вызывает любой конструктор любого глобального объекта.
Более эффективная стратегия состоит в использовании специфичных для потока счетчиков, чтобы потоки не конкурировали при увеличении общего счетчика.