Синхронизированная многопоточность против одиночного потока

Я пытаюсь подсчитать 100 чисел с помощью многопоточности и однопоточности. Поскольку ключевое слово synchronized допускает только один поток за раз (это похоже на один поток), поэтому эти два метода ниже должны иметь примерно одинаковое время выполнения, если мы игнорируем эффект затрат времени на создание и синхронизацию потоков?

Многопоточность с использованием синхронизированного:

public synchronized static void increment() {
    sum++;
}

public static void main(String[] args) {
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                increment();
            }
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 50; i++) {
                increment();
            }
        }
    });
    t1.start();;
    t2.start();
    try {
        t1.join();
        t2.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(sum);

Однопоточность:

public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
        sum++
    }

    System.out.println(sum);
}

person SHE    schedule 07.06.2016    source источник
comment
Что такое t1 во втором подходе? Вы имеете в виду t3?   -  person Andy Turner    schedule 07.06.2016
comment
Да. Я отредактировал это. @Энди Тернер   -  person SHE    schedule 07.06.2016
comment
Однопоточность с использованием synchronized: на самом деле это многопоточность. У вас есть основной поток и t3. И вы не используете synchronized.   -  person Andy Turner    schedule 07.06.2016
comment
Виноват. Пожалуйста, смотрите мое редактирование. @Энди Тернер   -  person SHE    schedule 07.06.2016
comment
Что ты вообще здесь спрашиваешь?   -  person Andy Turner    schedule 07.06.2016
comment
Мой вопрос заключается в том, что синхронизированная многопоточность ведет себя аналогично однопоточности и должно иметь примерно одинаковое время выполнения? @Энди Тернер   -  person SHE    schedule 07.06.2016
comment
Это не анализирует. Если вы спросите, ведут ли они себя одинаково? На что ответ да - значение sum будет равно 100 в конце обоих.   -  person Andy Turner    schedule 07.06.2016
comment
Если не учитывать влияние затрат времени на создание и синхронизацию потоков, время их выполнения должно быть примерно одинаковым? @Энди Тернер   -  person SHE    schedule 07.06.2016
comment
Если вы проигнорируете время, затрачиваемое на выполнение всех вещей, которые различаются между ними, да, они занимают одинаковое время для запуска.   -  person Andy Turner    schedule 07.06.2016
comment
Независимо от языка программирования или способа координации, чтобы потоки не мешали друг другу, вы распространяете последовательный алгоритм на несколько потоков. Это гарантированно никогда не будет быстрее (при идеальном планировании), чем за один раз.   -  person zapl    schedule 07.06.2016
comment
Для большего количества и однопоточного случая JIT может полностью исключить цикл и просто распечатать счет. Для многопоточного случая этого сделать нельзя, поэтому многопоточный код будет намного медленнее.   -  person Thomas Kläger    schedule 07.06.2016


Ответы (1)


Java действительно хорошо справляется с многопоточностью, но при создании и синхронизации потоков возникает много накладных расходов, поэтому не удивляйтесь, если для простой задачи, такой как счет до 100, вы действительно увидите увеличение времени выполнения.

person Scott Twombly    schedule 07.06.2016
comment
Если не учитывать влияние затрат времени на создание и синхронизацию потоков, время их выполнения должно быть примерно одинаковым? @Скотт Твомбли - person SHE; 07.06.2016
comment
Конечно, но я считаю, что это неразумно. Вы не можете отделить jvm от java. Если вы хотите просто подсчитать, сколько раз число увеличивается, они, конечно, одинаковы в обоих сценариях, но это почти бессмысленная метрика. В вашем многопоточном примере происходит гораздо больше вещей и методов, вызываемых под капотом, игнорирование их заставляет меня задаться вопросом, какой смысл сравнивать эти вещи в первую очередь? @ОНА - person Scott Twombly; 07.06.2016
comment
@SHE, вы упускаете из виду точку зрения Томаса Клагера (см. Его комментарий к вашему вопросу выше). Хороший компилятор мог бы распознать, что sum, вычисленное в вашем однопоточном примере, не зависит ни от какой переменной, ни от какого вызова функции, ни от каких входных данных. Это просто константа. Это 4950, и всегда будет 4950. Хороший компилятор может заменить весь ваш цикл на sum = 4950;, и это не изменит вывод программы, но заставит ее работать намного быстрее. Но ни один компилятор не мог этого сделать для многопоточной версии. Слишком сложно. - person Solomon Slow; 07.06.2016