Как const
(указатели, ссылки и функции-члены) помогают с безопасностью потоков в C++?Безопасность потока и `const`
ответ
Основная проблема с несколькими потоками - изменчивость. const ограничивает это, но поскольку вы можете отбросить константу, она не является надежной.
Любые неизменяемые (то есть неотменяемые) данные по сути являются потокобезопасными - нет риска для нескольких потоков, одновременно считывающих одни и те же данные только для чтения, потому что это никогда не изменится!
Маркировка переменной как const в C++ делает ее доступной только для чтения и, таким образом, безопасную для потоков.
Предполагая, что вы не используете изменяемый нигде ;-) – 2008-12-12 09:30:42
И если предположить, что инициализация является потокобезопасной. – xtofl 2008-12-12 10:17:48
Функция const member не должна изменять состояние, которое позволяет безопасно звонить из нескольких потоков одновременно. Однако безопасность потоков не является целью const, а C++ предоставляет изменяемое ключевое слово и const_cast, что означает, что const не гарантирует безопасность потоков и не следует полагаться на эти цели.
Конструктивные функции не являются потокобезопасными. Нормальный, вы можете одновременно вызывать методы const object из разных потоков, но если вы вызываете метод non const и const из разных потоков, вы получаете условие гонки. Проверьте это:
class Foo
{
size_t size_;
public:
...
size_t get_size() const
{
return size_
}
};
class Bar
{
boost::shared_ptr<Foo> foo_;
public:
//accessor
size_t get_size() const
{
size_t size = 0;
if (foo_)
size = foo_->size();
return size;
}
//modifiers
void init()
{
foo_ = new Foo;
}
void clear()
{
foo_ = boost::shared_ptr<Foo>();
}
};
Если кто-то вызов метода инициализации, а затем вызвать ясно и get_size методы одновременно, это приведет к нарушению прав доступа. Вы должны использовать идиом блокировки чтения. Одновременно можно вызывать несколько аксессуаров, и одновременно можно вызывать только один модификатор. Exemple:
class Bar
{
boost::shared_ptr<Foo> foo_;
mutable tbb::spin_rw_mutex lock_;
public:
//accessor
size_t get_size() const
{
size_t size = 0;
//lock modifiers
rw_mutex_type::scoped_lock lock(mutex, false);
if (foo_)
size = foo_->size();
return size;
}
//modifiers
void init()
{
//lock accessor and modifiers
rw_mutex_type::scoped_lock lock(mutex, true);
foo_ = new Foo;
}
void clear()
{
//lock accessor and modifiers
rw_mutex_type::scoped_lock lock(mutex, true);
foo_ = boost::shared_ptr<Foo>();
}
};
TBB :: spin_rw_lock класс мьютекс из threading builing blocks library
C++ Const позволяет неконстантная сглаживание, такие как:
Foo myVar;
const Foo* ptr1;
Foo* ptr2;
Учитывая это, сопзЬ не дает никаких гарантий в отношении неизменность ваших данных, даже если вы не делаете кастинг или что-либо, чтобы обойти его. Если вы обращаетесь к myVar через ptr1, вы не можете изменить его через ptr1 (если я правильно понял синтаксис, это было намерение.) Однако он все равно может измениться через ptr2. То, что вы действительно хотите, - это отдельная непреложная конструкция. Это не существует в C++.
Const and thread safety - это ортогональные концепции.
Возьмите функцию const в качестве примера: класс может иметь как константные, так и неконстантные функции, а один поток может вызывать неконстантную функцию, которая модифицирует объект, в то время как другой поток находится в его функции const , В этом случае маркировка функции const не обеспечивает никакой безопасности. Защита резьбы достигается только с помощью фиксаторов или других примитивов синхронизации.
Это не так. Просто потому, что ссылка на переменную является константой, не означает, что для этой переменной нет ссылок не const. – 2016-05-25 13:07:53
@ChrisBecke По общему признанию, этот http://stackoverflow.com/questions/14127379/does-const-mean-thread-safe-in-c11 - гораздо лучший вопрос, который задают более подробно. Я думаю, что ответы там показывают, что glib «это не так» недостаточно. – 2016-05-31 10:23:24