Разделить строку в Java со специальным символом только в первом случае?

Секундомер не является потокобезопасным, особенно для 32-разрядных программ.

Он использует вызов Windows API QueryPerformanceCounter() для обновления частного длинного поля. В 32-битных системах вы можете получить «рваное чтение», когда один поток читает длинное значение, а другой поток обновляет его.

Чтобы исправить это, вам нужно будет заблокировать доступ к Секундомер.

Также обратите внимание, что в некоторых старых системах были ошибки, в которых непоследовательные значения могли быть возвращены из разных потоков, вызывающих QueryPerformanceCounter(). Из документации:

На многопроцессорном компьютере не должно иметь значения, какой процессор вызывается. Тем не менее, вы можете получить разные результаты на разных процессорах из-за ошибок в базовой системе ввода / вывода (BIOS) или слоя абстракции аппаратного обеспечения (HAL). Чтобы указать сродство процессора к потоку, используйте функцию SetThreadAffinityMask.

blockquote>

Я никогда не сталкивался с этой ошибкой сам, и я не думаю, что это очень распространено.

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

namespace Demo
{
    class Program
    {
        Stopwatch sw = Stopwatch.StartNew();

        object locker = new object();
        ConcurrentQueue queue = new ConcurrentQueue();
        Barrier barrier = new Barrier(9);

        void run()
        {
            Console.WriteLine("Starting");

            for (int i = 0; i < 8; ++i)
                Task.Run(()=>test());

            barrier.SignalAndWait(); // Make sure all threads start "simultaneously"
            Thread.Sleep(2000); // Plenty of time for all the threads to finish.

            Console.WriteLine("Stopped");

            foreach (var elapsed in queue)
                Console.WriteLine(elapsed);

            Console.ReadLine();
        }

        void test()
        {
            barrier.SignalAndWait(); // Make sure all threads start "simultaneously".

            for (int i = 0; i < 10; ++i)
                queue.Enqueue(elapsed());
        }

        long elapsed()
        {
            lock (locker)
            {
                return sw.ElapsedTicks;
            }
        }

        static void Main()
        {
            new Program().run();
        }
    }
}

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

0
задан Alan Moore 24 September 2012 в 10:55
поделиться