1. C# / Говнокод #20034

    +2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    private long m_IsExecuting;
    
    // ...
    
    public virtual void Execute(object parameter)
    {
    	try
    	{
    		if (Interlocked.Read(ref m_IsExecuting) != 0)
    			return;
    		Interlocked.Increment(ref m_IsExecuting);
    		m_Execute(parameter);
    	}
    	finally
    	{
    		Interlocked.Decrement(ref m_IsExecuting);
    	}
    }

    А за то, что ты меня не пустил, я пущу следующего.

    Запостил: yamamoto, 18 Мая 2016

    Комментарии (12) RSS

    • Слона то вы батенька и не заметили
      Класс Interlocked гарантирует атомарность операция только в своих методах, поэтому при переключении потоков между 9 и 11 строкой ваша блокировка идёт по пизде.
      Но патч в виде
      if (Interlocked.Increment(ref m_IsExecuting) != 1) return;

      вместо строк 9 - 11 решил бы сразу две проблемы
      Ответить
      • Спасибо, кэп!
        Но пропуск каждого второго выглядит забавнее :)
        Ответить
      • иными словами операции Interlocked атомарны, но между ними может произойти переключение поток. Верно?
        Ответить
      • Не решил бы. Для первого запуска сработает, но для второго проблема в том, что декремент не обнулит приватку, ибо хуй его знает, сколько раз была проверка с побочным инкрементом.
        Ответить
        • Декремент обнулит так как вызывается даже после return
          Ответить
        • return передаёт управление на finally. Декремент рано или поздно сработает, хоть при пропуске m_Execute, хоть после выполнения. Да, m_IsExecuting может принимать значения больше единицы, но после прохождения Execute всеми потоками получим ноль.

          Неприятность возникнет только в случае необработанного исключения, поскольку секции catch у нас нет. Тогда выполнение может быть заблокировано навсегда.
          Ответить
          • Не возникнет блок finally выполняется даже если catch исключение не ловить исключение просто пробрасывается дальше
            Ответить
            • Тогда выходит, что проблема решена.

              Я решил подстраховаться, потому что тут было предупреждение:
              https://msdn.microsoft.com/ru-ru/library/zwc8s4fz.aspx
              Но там уже про крайний случай, когда приложение должно аварийно завершиться.
              Ответить
              • Обработка необработанных исключений

                Какие-то взаимоисключающие параграфы...
                Ответить
                • Вся Винда — это скопление взаимоисключающих параграфов.

                  Windows производит настройку самонастраивающихся устройств.
                  Ответить

    Добавить комментарий