На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (16) « Первая ... 2 3 [4] 5 6 ...  15 16 все  ( Перейти к последнему сообщению )  
> Thread-safe shared_ptr , Реализация потоко-безопасного SharedPtr
    Нет, не так. Здесь первый поток ресетит shared_ptr, sp, и присваивает его weak_ptr'у, sp2. Второй поток вызывает weak_ptr::lock, те создаёт новый shared_ptr, и, если он не null, обращается к его содержимому. Для std::shared_ptr это не работает, для CSharedPtr всё нормально
      Олег М, вот какая проблема с многопотоковостью SP.
      1. Несколько экземпляров SP указывают на объект выбранного типа.
      2. Другие несколько экземпляров - на другой объект этого-же типа.
      3. SP - это шаблонный класс. Значит, возможно наличие групп SP,
      указывающих на объекты любых других типов.

      Необходимо, чтобы потоко-безопасность обеспечивалась для каждой
      группы отдельно. Иначе манипуляции со счётчиком ссылок одной группы
      будут влиять на манипуляциями со счётчиками любой другой группы SP.
      А это как раз и не очень хорошо.
        Цитата Олег М @
        Нет, не так.

        Смотри.
        Строчка 9:
        Цитата Олег М @
        ExpandedWrap disabled
          threads.emplace_back(std::make_unique<std::thread>([&sp, &sp2, &stop]()

        - ты передаёшь в поток оба указателя по ссылке.

        Строчка 13:
        Цитата Олег М @
        ExpandedWrap disabled
          sp.reset(new std::string("!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111111111111111111111111111111"));

        Ты в нескольких потока одновременно модифицируешь один и тот же shared_ptr. То есть незащищённый конкурентный доступ к внешнему ресурсу.

        Строчка 14:
        Цитата Олег М @
        ExpandedWrap disabled
          sp2 = sp;

        Ты так же конкурентно (как и в предыдущей строке) модифицируешь разделяемый weak_ptr. Один и тот же во всех потоках.

        Строчка 18:
        Цитата Олег М @
        ExpandedWrap disabled
          threads.emplace_back(std::make_unique<std::thread>([&sp2, &stop]()

        Передаёшь ещё в один поток ссылку на внешний weak_ptr.

        Строчка 18:
        Цитата Олег М @
        ExpandedWrap disabled
          auto sp = sp2.lock();

        Пытаешься залочить внешний weak_ptr, который активно (без синхронизации) меняется из соседнего потока.
        Ты, конечно, можешь ожидать, что будет создана отдельная копия shared_ptr'а на какой-то указатель, но если повезёт, твоя программа свалится с внятной диагностикой. Ибо тут самый что ни наесть типовой data race. Если не повезёт - отправится SMS на адрес Трампа и он нажмёт на красную кнопку в своём ядерном чемоданчике. :) Undefined Behavior - он такой. :)
        Сообщение отредактировано: Flex Ferrum -
          Имеешь ввиду template <typename T> CSharedPtrLock &GetSharedPtrLock() и, соответственно, CSharedPtrBase::GetSharedRef()?

          Добавлено
          Flex Ferrum
          Цитата Flex Ferrum @
          Ты, конечно, можешь ожидать, что будет создана отдельная копия shared_ptr'а на какой-то указатель, но если повезёт, твоя программа свалится с внятной диагностикой. Ибо тут самый что ни наесть типовой data race. Если не повезёт - отправится SMS на адрес Трампа и он нажмёт на красную кнопку в своём ядерном чемоданчике. Undefined Behavior - он такой.

          Ну, во-первых не сваливается, работает. Во-вторых как раз эти функции и являются потоко-безопасными. Я там не ожидаю, я точно знаю, что будет создано return CSharedPtr<T>(GetSharedRef<T>());

          Добавлено
          ЫукпШ Имеешь ввиду template <typename T> CSharedPtrLock &GetSharedPtrLock() и, соответственно, CSharedPtrBase::GetSharedRef()?
          Очень похоже на адский косяк, сижу, думаю
            Цитата Олег М @
            Ну, во-первых не сваливается, работает.

            Я говорю про работу с shared_ptr. Как аргумент к тому, что конкретно этот пример разделяемым ресурсом считает сам указатель (CSharedPtr/CWeakPtr в твоей терминологии), а не CSharedPtrBase.
              Цитата Олег М @
              Пытаешься залочить внешний weak_ptr, который активно (без синхронизации) меняется из соседнего потока.

              Вообще, там вроде всё синхронизируется, в конструкторах/деструкторах
                Цитата Олег М @
                Вообще, там вроде всё синхронизируется, в конструкторах/деструкторах

                В стандартном? Нет. Не лочится. И не должно - это не требуется стандартом. А работа с атомиками (как я уже говорил) - это не локи. Это просто работа с атомиками.
                  Цитата Олег М @
                  Я говорю про работу с shared_ptr. Как аргумент к тому, что конкретно этот пример разделяемым ресурсом считает сам указатель (CSharedPtr/CWeakPtr в твоей терминологии), а не CSharedPtrBase.

                  Доступ к самому указателю синхронизируется при помощи счётчика CSharedCounter. Что именно неправильно, и как должно быть?

                  Добавлено
                  Цитата Flex Ferrum @
                  В стандартном? Нет. Не лочится. И не должно - это не требуется стандартом. А работа с атомиками (как я уже говорил) - это не локи. Это просто работа с атомиками.


                  В стандартном да, не работает. Я где-то видел, что они планируют, сходу не могу найти где. У меня вроде работает. Работа с атомиками - это lock-free блокировка, чем то-хуже, чем-то лучше мьютексов.
                    Цитата Олег М @
                    Доступ к самому указателю синхронизируется при помощи счётчика CSharedCounter. Что именно неправильно, и как должно быть?

                    Ещё раз: я говорю про работу этого кода с std::shared_ptr/std::weak_ptr. :)

                    Добавлено
                    Цитата Олег М @
                    В стандартном да, не работает. Я где-то видел, что они планируют, сходу не могу найти где. У меня вроде работает. Работа с атомиками - это lock-free блокировка, чем то-хуже, чем-то лучше мьютексов.

                    Работа с атомиками - это работа с атомиками. То есть работа с памятью с учётом особенностей многопоточной и многопроцессорной среды. Но не более того. Рассматривать это как блокировку (или варианты блокировки) - это обманывать самого себя.
                      Цитата Flex Ferrum @
                      Ещё раз: я говорю про работу этого кода с std::shared_ptr/std::weak_ptr.

                      Я ж вроде и говорил, что он не работает, именно поэтому пришлось писать свои классы. И?
                        Цитата Олег М @
                        И?

                        Я до сих пор не догоняю, какая именно реальная задача решается таким вот сценарием:
                        Цитата Олег М @
                        Здесь первый поток ресетит shared_ptr, sp, и присваивает его weak_ptr'у, sp2. Второй поток вызывает weak_ptr::lock, те создаёт новый shared_ptr, и, если он не null, обращается к его содержимому. Для std::shared_ptr это не работает, для CSharedPtr всё нормально
                          Цитата Flex Ferrum @
                          Работа с атомиками - это работа с атомиками. То есть работа с памятью с учётом особенностей многопоточной и многопроцессорной среды. Но не более того. Рассматривать это как блокировку (или варианты блокировки) - это обманывать самого себя.


                          Ну почему обманывать, у lock-free алгоритмов есть масса преимуществ, особенно на многопроцессорных серверах. Есть и свои недостатки. Я в них не особо разбираюсь, поэтому в данном случае мне больше нравится, что они занимают много меньше памяти - 8 байт против 40 для мьютекса

                          Добавлено
                          Реальная задача чуть позже. Надо как-то сформулировать. Запустил-таки всю эту бадягу на боевом сервере, наблюдаю, не могу толком ни на чём другом сосредоточиться
                            Цитата Олег М @
                            Ну почему обманывать, у lock-free алгоритмов есть масса преимуществ, особенно на многопроцессорных серверах.

                            lock-free-алгоритмы - это одно из средств применения атомиков. Причём весьма специфичная. Средствами синхронизации атомики от этого не становятся.
                              Почему? Есть возможность сделать так, чтоб один поток, подождал пока другой поток не освободил ресурс. Это ли не синхронизация?
                                Цитата Олег М @
                                Почему? Есть возможность сделать так, чтоб один поток, подождал пока другой поток не освободил ресурс. Это ли не синхронизация?

                                Даже если ты делаешь синхронизацию на спинлоках - это все равно лочка, и алгоритм с такой синхронизацией lock-free назвать уже нельзя. :)
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (16) « Первая ... 2 3 [4] 5 6 ...  15 16 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0450 ]   [ 16 queries used ]   [ Generated: 2.05.24, 09:39 GMT ]