Потокобезопасность и 'константа'

Итак, я смог найти решение после нескольких часов борьбы.

Оказывается, мне не нужно ни настаивать, ни сбрасывать изменения. Решение состоит в том, чтобы использовать Unit of Work для пересчета изменений в $ parent, а затем доктрина сбросит их самостоятельно. Мне также пришлось изменить способ подсчета продуктов, так как на этапе предварительной проверки изменения еще нет в базе данных, поэтому запрос не будет работать должным образом. Вот почему я считаю их вручную, обходя дерево отношений.

Вот пример кода.

public function preFlush(Room $room, PreFlushEventArgs $args)
  {
    $em = $args->getEntityManager();
    $numOfProducts = 0;
    $parent = $room->getStore()->getParent();
    foreach($parent->getStores() as $store) {
      foreach($store->getRooms() as $room) {
        $numOfServices += count($room->getProducts());
      }
    }
    $parent->setNumberOfProducts($numOfProducts);
    $classMetadata = $em->getClassMetadata(get_class($parent));
    $em->getUnitOfWork()->computeChangeSet($classMetadata, $parent);
  }
9
задан James Hopkin 12 December 2008 в 09:01
поделиться

5 ответов

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

6
ответ дан 4 December 2019 в 06:31
поделиться

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

Отмечание переменной как константа в C++ делает это только для чтения и таким образом ориентированным на многопотоковое исполнение.

14
ответ дан 4 December 2019 в 06:31
поделиться

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

6
ответ дан 4 December 2019 в 06:31
поделиться

Функции константы не ориентированы на многопотоковое исполнение. Normaly, можно назвать методы объекта константы от различных потоков одновременно, но если Вы называете не константу и метод константы от различных потоков, Вы получаете состояние состязания. Проверьте это:

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>();
    }
};

Если кто-то назовет init метод и затем назовет четкие и 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 является взаимоисключающим классом от поточной обработки библиотеки блоков здания

4
ответ дан 4 December 2019 в 06:31
поделиться

Константа C++ позволяет неконстанту, искажающую, такую как:

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

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

4
ответ дан 4 December 2019 в 06:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: