Синхронизированный код работает быстрее, чем несинхронизированный - PullRequest
3 голосов
/ 10 сентября 2011

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

private static final ConcurrentHashMap<Double,Boolean> mapBoolean = 
        new ConcurrentHashMap<Double, Boolean>();
private static final ConcurrentHashMap<Double,LinkedBlockingQueue<Runnable>> map
        = new ConcurrentHashMap<Double, LinkedBlockingQueue<Runnable>>();


protected static <T> Future<T> execute(final Double id, Callable<T> call){
// where id is the ID number of each thread
synchronized(id)
{
   mapBoolean.get();// then do something with the result
   map.get();//the do somethign with the result
}
}

protected static <T> Future<T> executeLoosely(final Double id, Callable<T> call){

 mapBoolean.get();// then do something with the result
 map.get();//the do somethign with the result

 }

}

При профилировании с более чем 500я обнаружил, что execute (..) выполняет по крайней мере в 500 раз лучше, чем executeLoosely (..), что странно, потому что executeLoosely не синхронизируется и, следовательно, большее количество потоков может обрабатыватькод одновременно.

Любые причины ??

Ответы [ 2 ]

4 голосов
/ 10 сентября 2011

Затраты на использование 500 потоков на машине, которые, как я полагаю, не имеют 500 ядер, используют задачи, которые занимают примерно 100-1000x, пока поиск по карте для выполнения кода, который может обнаружить JVM, не делаетвсе, что может привести к случайному результату.;)

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

Вы должны сравнить время, которое вы получаете с одним потоком, выполняющим цикл.Если это быстрее (что, я думаю, так и будет), то это бесполезный многопоточный тест.

Я предполагаю, что вы запускаете синхронизированный код после несинхронизированного кода.т.е. после того как JVM немного прогрелась.Поменяйте местами порядок выполнения этих тестов и запустите их много раз, и вы получите разные результаты.

0 голосов
/ 10 сентября 2011

В несинхронизированном сценарии: 1) дождаться получения блокировки на сегменте карты, заблокировать, выполнить операцию на карте, разблокировать, дождаться получения блокировки на сегменте другой карты, заблокировать, выполнить операцию на другой карте, разблокировать. Блокировка на уровне сегмента будет выполняться только в случаях одновременной записи в сегмент, что в вашем примере не выглядит так.

В синхронизированном сценарии: 1) дождаться блокировки, выполнить обе операции, разблокировать.

Время, затраченное на переключение контекста, может оказать влияние? Сколько ядер у машины, на которой выполняется тест? Как устроены карты, такие же ключи?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...