На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
Страницы: (16) « Первая ... 3 4 [5] 6 7 ...  15 16 все  ( Перейти к последнему сообщению )  
> Thread-safe shared_ptr , Реализация потоко-безопасного SharedPtr
    Убрал template c GetSharedPtrLock(). Теперь они все будут лочиться одним счётчиком. Плохо конечно, но не смертельно. Понять, это ли было причиной ошибки на сервере я не смог, но в случае с потоками лучше перебдеть

    Добавлено
    Цитата Flex Ferrum @
    Даже если ты делаешь синхронизацию на спинлоках - это все равно лочка, и алгоритм с такой синхронизацией lock-free назвать уже нельзя


    А разве не именно такие алгоритмы называются lock-free? Которые блокируют ресурс не усыпляя потока?
      Цитата Олег М @

      А разве не именно такие алгоритмы называются lock-free? Которые блокируют ресурс не усыпляя потока?

      Если я всё правильно понимаю, то нет:
      Цитата
      Для алгоритмов без блокировок гарантируется системный прогресс по крайней мере одного потока. Например, поток, выполняющий операцию «сравнение с обменом» в цикле, теоретически может выполняться бесконечно, но каждая его итерация означает, что какой-то другой поток совершил прогресс, то есть система в целом совершает прогресс.


      Добавлено
      В вики на этот счёт всё хорошо расписано.
        Цитата Flex Ferrum @
        Если я всё правильно понимаю, то нет:
        Цитата


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

          Нет. Самый дорогой ресурс - процессорное время.
          Если потоку не нужно работать, пусть остановится.
            Цитата ЫукпШ @
            Нет. Самый дорогой ресурс - процессорное время.
            Если потоку не нужно работать, пусть остановится.


            Тут я не соглашусь. Остановка-запуск потока далеко не бесплатные операции и их тоже выполняет тот же самый процессор.
              Цитата Олег М @
              Цитата Flex Ferrum @
              Если я всё правильно понимаю, то нет:
              Цитата


              Судя по цитате, понимаешь неправильно. Но не буду тут спорить, я в этом не большой специалист. Моё понимание таково - усыплять поток, потом будить - это дорого. Для многопроцессорных систем дешевле, чтоб этот поток покрутился в цикле, пока другой поток, который как правило крутится на другом другом процессоре, освободит ресурс. Единственная проблема там - в атомик-блокировках, о которых я знаю совсем мало, но говорят, что они тоже нифига не бесплатные.

              Весьма ошибочное суждение. Потоков в системе обычно на порядки больше, чем голов у процессора. Поэтому система шедулрует на одном процессоре/голове несколько десятков, если не сотен, потоков. И если какой-то из потоков начнёт крутить пустой цикл - он впустую сжигает ватты и мешает работать другим. Кстати, именно этим плохи спинлоки, особенно самопальные.

              Дорого контекстами щелкать - прыгать от одного потока к другому и обратно (т. н. "дребезг") - вот это да, действительно дорого. Поток должен стараться с максимальной пользой утилизировать свои кванты. Этим и хороши lock-free алгоритмы (при грамотно использовании) - на критических путях нету взаимных блокировок и простоев. Но и они не панацея.
              Сообщение отредактировано: Flex Ferrum -
                А чем самопальные спинлоки отличаются о не-самопальных.

                Добавлено
                Цитата Flex Ferrum @
                Дорого контекстами щелкать - прыгать от одного потока к другому и обратно (т. н. "дребезг") - вот это да, действительно дорого. Поток должен стараться с максимальной пользой утилизировать свои кранты. Этим и хороши lock-free алгоритмы (при грамотно использовании) - на критических путях нету взаимных блокировок и простоев. Но и они не панацея.


                Что-то ни слова не понял. Что значит "щёлкать контекстами" - усыплять один поток и пробуждать другой, разве мьютексы так и не делают? Что значит нету взаимных блокировок - куда ж они тогда деваются?
                  Цитата Олег М @
                  А чем самопальные спинлоки отличаются о не-самопальных.

                  Тем, что могут не учитывать особенности работы системы, быть написанными топорно. Системные примитив синхронизацию обычно оптимизированы под "короткие" блокировки и не проваливаются лишний раз в ядро.
                    Цитата Flex Ferrum @
                    Тем, что могут не учитывать особенности работы системы, быть написанными топорно.


                    А как цикл с compare_exchange может не учитывать особенности работы системы? Или учитывать?
                      Цитата Flex Ferrum @
                      1. У меня там, в Release, вроде префиксный декремент, return --m_cnt == 0; И он проверяется на ноль. В AddRef проверка на ноль нужна, чтобы не захватывать удаляемый элемент.

                      Это я к тому, что и в AddRef можно так же делать. К слову, все так и делают.


                      В смысле, ты имеешь ввиду, почему я не делаю AddRef () {return ++m_cnt != 1;}? Потому что так нельзя. Если счётчик равен нулю, то его нельзя увеличивать, иначе когда несколько потоков будут одновременно вызывать AddRef(), только одному вернётся false, остальным - true и указатель на объект который был удалён.
                        Итак - зачем мне это нужно?
                        1. Тренировка мозгов. Когда работаешь с потоками ошибку сделать легко, но найти её можно только путём пристального разглядывания и анализа исходного кода. Для этого нужно всегда быть в форме и помнить о нюансах и правилах. Lock-free алгоритмы - хорошая тренировка.

                        Добавлено
                        2. Повторное использования кода. Когда тебе постоянно приходится блокировать экземпляр какого-то класса, придумывать названия для мьютексов, следить, чтобы они блокировались-разблокировались вовремя и тд и тп, поневоле задумаешься - а не сделать ли этот класс потоко-безопасным? Потратить один раз время и забыть об этих проблемах. C классами типа контейнеров, строк и т.д. это делать тяжеловато, да и особо не нужно - они блокируются относительно редко и по-разному. Но указатели - другое дело, они простые, и они используются часто.

                        Добавлено
                        3. Минимизация времени блокировки. Не думаю (вернее, не знаю как), что можно заблокировать shared_ptr на меньшее время, причём независимо от других указателей. Например есть большое количество объектов, которые создаются/удаляются в одних потоках, обрабатываются в других. Для решения этой задачи я пользуюсь следующим методом:
                        - В обработчике хранится список list<weak_ptr> и мьютекс
                        - Когда мне надо что-то с ним сделать, я блокирую этот мьютекс, переношу список в локальную переменную при помощи move-конструктора, разблокирую
                        - Пробегаюсь по локальному списку, если weak_ptr::lock возвращает null, удаляю из локального списка, иначе вызываю какую-нибудь функцию
                        - Снова блокирую список, делаю list::splice, т.е. возвращаю не удалённые объекты обратно
                        Все операции копеечные и никаких дедлоков
                          смотрел смотрел твой код.. сложно не разобраться добавь комментов плз :D
                            Цитата Олег М @
                            3. Минимизация времени блокировки.

                            Критическая секция - вероятно, самый быстрый вариант.
                            ---
                            Тренировка - это отлично. А результат достигнут ?
                            Сообщение отредактировано: ЫукпШ -
                              Цитата ЫукпШ @
                              Критическая секция - вероятно, самый быстрый вариант.
                              ---
                              Тренировка - это отлично. А результат достигнут ?

                              Тут спорный вариант, но примерно такой же, но, в любом случае занимает больше памяти.
                              Результат чего? Код вроде работает, пока. Завтра вечером можно будет сказать более определённо. В выходные коннекто мало.

                              Добавлено
                              Цитата Cfon @
                              смотрел смотрел твой код.. сложно не разобраться добавь комментов плз


                              С этим сложнее, никогда не умел писать комментарии. Лучше спроси, что непонятно – я отвечу.
                                Цитата Олег М @
                                Результат чего? Код вроде работает, пока. Завтра вечером можно будет сказать более определённо.

                                Вот посмотри тут.
                                Ты пишешь:
                                ExpandedWrap disabled
                                          void lock() noexcept
                                      {
                                          ++m_cnt;
                                      }


                                Будет ли этот инкремент - потокобезопасным ?
                                Чисто случайно, я посмотрел ассемблерный текст одного из скомпилированных модулей.
                                И вот что получилось - вот оно:
                                ExpandedWrap disabled
                                  //..
                                   ++Count;
                                  //..

                                стало:
                                ExpandedWrap disabled
                                  ; 191  :  ++Count;
                                   
                                    0003e a1 00 00 00 00   mov     eax, DWORD PTR ?Count@@3HA ; Count
                                    00043 40       inc     eax
                                    00044 a3 00 00 00 00   mov     DWORD PTR ?Count@@3HA, eax ; Count

                                Никакой потокобезопасностью даже не пахнет.
                                3 машинные команды, передача управления другому потоку может произойти между ними.
                                Хотя казалось что будет что-то вроде (но увы..):
                                ExpandedWrap disabled
                                              inc DWORD PTR Count
                                Сообщение отредактировано: ЫукпШ -
                                1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (16) « Первая ... 3 4 [5] 6 7 ...  15 16 все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0979 ]   [ 15 queries used ]   [ Generated: 17.05.24, 13:05 GMT ]