2008-12-12 3 views
9

Как const (указатели, ссылки и функции-члены) помогают с безопасностью потоков в C++?Безопасность потока и `const`

+0

Это не так. Просто потому, что ссылка на переменную является константой, не означает, что для этой переменной нет ссылок не const. – 2016-05-25 13:07:53

+0

@ChrisBecke По общему признанию, этот http://stackoverflow.com/questions/14127379/does-const-mean-thread-safe-in-c11 - гораздо лучший вопрос, который задают более подробно. Я думаю, что ответы там показывают, что glib «это не так» недостаточно. – 2016-05-31 10:23:24

ответ

6

Основная проблема с несколькими потоками - изменчивость. const ограничивает это, но поскольку вы можете отбросить константу, она не является надежной.

14

Любые неизменяемые (то есть неотменяемые) данные по сути являются потокобезопасными - нет риска для нескольких потоков, одновременно считывающих одни и те же данные только для чтения, потому что это никогда не изменится!

Маркировка переменной как const в C++ делает ее доступной только для чтения и, таким образом, безопасную для потоков.

+0

Предполагая, что вы не используете изменяемый нигде ;-) – 2008-12-12 09:30:42

+1

И если предположить, что инициализация является потокобезопасной. – xtofl 2008-12-12 10:17:48

6

Функция const member не должна изменять состояние, которое позволяет безопасно звонить из нескольких потоков одновременно. Однако безопасность потоков не является целью const, а C++ предоставляет изменяемое ключевое слово и const_cast, что означает, что const не гарантирует безопасность потоков и не следует полагаться на эти цели.

4

Конструктивные функции не являются потокобезопасными. Нормальный, вы можете одновременно вызывать методы 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

4

C++ Const позволяет неконстантная сглаживание, такие как:

Foo myVar; 
const Foo* ptr1; 
Foo* ptr2; 

Учитывая это, сопзЬ не дает никаких гарантий в отношении неизменность ваших данных, даже если вы не делаете кастинг или что-либо, чтобы обойти его. Если вы обращаетесь к myVar через ptr1, вы не можете изменить его через ptr1 (если я правильно понял синтаксис, это было намерение.) Однако он все равно может измениться через ptr2. То, что вы действительно хотите, - это отдельная непреложная конструкция. Это не существует в C++.

3

Const and thread safety - это ортогональные концепции.

Возьмите функцию const в качестве примера: класс может иметь как константные, так и неконстантные функции, а один поток может вызывать неконстантную функцию, которая модифицирует объект, в то время как другой поток находится в его функции const , В этом случае маркировка функции const не обеспечивает никакой безопасности. Защита резьбы достигается только с помощью фиксаторов или других примитивов синхронизации.