Я играл с фреймворком Disruptor и его портом для платформы .NET и нашел интересный случай. Может быть, я что-то совсем упустил, поэтому ищу помощи у всемогущего сообщества .
long iterations = 500*1000*1000;
long testValue = 1;
//.NET 4.0. Release build. Mean time - 26 secs;
object lockObject = new object();
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
lock (lockObject)
{
testValue++;
}
}
sw.Stop();
//Java 6.25. Default JVM params. Mean time - 17 secs.
Object lock = new Object();
long start = System.currentTimeMillis();
for (int i = 0; i < iterations; i++)
{
synchronized (lock)
{
testValue++;
}
}
long stop = System.currentTimeMillis();
Похоже, что получение блокировки в сценарии с помощью единственного потока в .NET стоит всего на 50% дороже, чем в Java . Сначала я с подозрением относился к таймерам, но я несколько раз запускал один и тот же тест с результатами, близкими к упомянутым выше средним значениям. Затем я с подозрением отнесся к блоку кода synchronized , но он делает не больше, чем просто monitorenter / monitorexit инструкции байтового кода - то же самое, что lock ключевое слово в .NET. Есть ли другие идеи, почему взятие блокировки так дорого в .NET и Java?
Java JIT оптимизирует синхронизацию, так как объект блокировки является локальным потоком (то есть он ограничен стеком потока и никогда не используется совместно) и, следовательно, никогда не может быть синхронизирован из другого потока. Я не уверен, что .NET JIT сделает это.
См. эту очень информативную статью , особенно часть, посвященную выбору замка.