powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / test synchronized vs ReentrantLock
49 сообщений из 49, показаны все 2 страниц
test synchronized vs ReentrantLock
    #38421390
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
помогите понять почему synchronized так сильно проигрывает ReentrantLock ?

run:
lock.lock()
5000000
Time spent: 0.234059174 sec

syninc
5000000
Time spent: 0.989136139 sec

у меня получается что с каждым новым тредом время растет линейно у synchronized! я начал с 2x тредов и до 5 !

Параметры JVM ставил разные :

XX:-UseBiasedLocking

секция synchronized - дорогая , возможно если поток завладел ей и его ОС отложила,то все остальные ждут

но если шедулер ОС остановит Lock, тоже все буду ждать, так же ? или нет ?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;


public class TwoThreads {

    public static int counter = 0;
    public static volatile int N = 1000000;
    public static Lock lock = new ReentrantLock();

    public synchronized static int getCounter() {
        return counter;
    }

    public static void inc() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }

    }

    public synchronized static void syninc() {
        counter++;
    }

    interface Lambda {

        void apply();
    }

    static long timeIt(Lambda lambda) {
        long start = System.nanoTime();
        lambda.apply();
        long end = System.nanoTime();
        long result = end - start;
        System.out.println("Time spent: " + (result) / 1000000000d + " sec\n");
        return result;
    }

    public static void main(String[] args) throws InterruptedException {

            System.out.println("lock.lock() ");
            timeIt(new Lambda() {
                @Override
                public void apply() {

                    Thread t1 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                inc();
                            }
                        }
                    });




                    Thread t2 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                inc();

                            }
                        }
                    });
                    Thread t3 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                inc();

                            }
                        }
                    });
                    Thread t4 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                inc();

                            }
                        }
                    });
                    Thread t5 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                inc();

                            }
                        }
                    });

                    t1.start();
                    t2.start();
                    t3.start();
                    t4.start();
                    t5.start();
                    try {
                        t1.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t2.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t3.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t4.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t5.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(counter);


                }
            });
            counter = 0;
            System.out.println("syninc ");
            timeIt(new Lambda() {
                @Override
                public void apply() {

                    Thread t1 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                syninc();
                            }
                        }
                    });




                    Thread t2 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                syninc();

                            }
                        }
                    });
                    
                    Thread t3 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                syninc();

                            }
                        }
                    });
                    Thread t4 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                syninc();

                            }
                        }
                    });
                    Thread t5 = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            for (int i = 0; i < N; i++) {
                                syninc();

                            }
                        }
                    });

                    t1.start();
                    t2.start();
                    t3.start();
                    t4.start();
                    t5.start();
                    try {
                        t1.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t2.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t3.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t4.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    try {
                        t5.join();
                    } catch (InterruptedException ex) {
                        Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                    }

                    System.out.println(counter);


                }
            });





    }
}
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421400
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Интересно посмотреть на код для 10 потоков.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421406
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczИнтересно посмотреть на код для 10 потоков.

:) просто копировал.
чтобы понять как растет время , а оно растет .
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421414
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А давайте в качестве эксперимента, поменяем очередность теста и посмотрим результат.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421420
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczА давайте в качестве эксперимента, поменяем очередность теста и посмотрим результат.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
                Thread[] threads = new Thread[threadCount];
                    for (int i = 0; i < threadCount; i++) {
                        threads[i] = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                for (int i = 0; i < N; i++) {
                                    inc();
                                }
                            }
                        });
                    }
                    
                    for (int i = 0; i < threads.length; i++) {
                        threads[i].start();
                    }
                    
                    for (int i = 0; i < threads.length; i++) {
                        try {
                            threads[i].join();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                    System.out.println(counter);
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421424
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По этим двум результатам запускал цикл . результаты примерно такие в серии из 100 циклов.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421436
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczА давайте в качестве эксперимента, поменяем очередность теста и посмотрим результат.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author i.salnikov
 */
public class TwoThreads {

    public static int counter = 0;
    public static int threadCount = 10;
    public static volatile int N = 1000000;
    public static Lock lock = new ReentrantLock();

    public synchronized static int getCounter() {
        return counter;
    }

    public static void inc() {
        lock.lock();
        try {
            counter++;
        } finally {
            lock.unlock();
        }

    }

    public synchronized static void syninc() {
        counter++;
    }

    interface Lambda {

        void apply();
    }

    static long timeIt(Lambda lambda) {
        long start = System.nanoTime();
        lambda.apply();
        long end = System.nanoTime();
        long result = end - start;
        System.out.println("Time spent: " + (result) / 1000000000d + " sec\n");
        return result;
    }
    
    
    public static void fThreadCount(int threadCountI, final Lambda lambda){
                   Thread[] threads = new Thread[threadCountI];
                    for (int i = 0; i < threadCountI; i++) {
                        threads[i] = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                for (int i = 0; i < N; i++) {
                                    lambda.apply();
                                }
                            }
                        });
                    }
                    
                    for (int i = 0; i < threads.length; i++) {
                        threads[i].start();
                    }
                    
                    for (int i = 0; i < threads.length; i++) {
                        try {
                            threads[i].join();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(TwoThreads.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }

                    System.out.println(counter);
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < threadCount; i++) {
           
            
      
            System.out.println("lock.lock() ");
            timeIt(new Lambda() {
                @Override
                public void apply() {
                 fThreadCount(threadCount,new Lambda() {
                     @Override
                     public void apply() {
                         inc();
                     }
                 });

                }
            });
            
            counter = 0;
            System.out.println("syninc ");
                     timeIt(new Lambda() {
                @Override
                public void apply() {
                 fThreadCount(threadCount,new Lambda() {
                     @Override
                     public void apply() {
                         syninc();
                     }
                 });

                }
            });
        }
    }
}
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421498
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здесь низкоуровневые объяснения
http://cheremin.blogspot.com/2011/11/synchronized-vs-reentrantlock.html
По всем остальным тестам в гугле - выводы такие же.
Lock как API имеет ряд фич, которые труднее реализовать с synchronized.
Lock действительно быстрее при высокой конкуретности. Т.е. как в вышеприведенном тесте, потоки постоянно в борьбе за ресурс.
synchronized будет быстрее в однопоточном исполнении за счет Biased Locking.
Разницы при небольшой конкуретности особой нет, можно пользовать и то и другое, к тому же объем критической секции почти всегда нивелирует разницу в производительности между этими блокировками.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421597
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczЗдесь низкоуровневые объяснения
http://cheremin.blogspot.com/2011/11/synchronized-vs-reentrantlock.html
По всем остальным тестам в гугле - выводы такие же.
Lock как API имеет ряд фич, которые труднее реализовать с synchronized.
Lock действительно быстрее при высокой конкуретности. Т.е. как в вышеприведенном тесте, потоки постоянно в борьбе за ресурс.
synchronized будет быстрее в однопоточном исполнении за счет Biased Locking.
Разницы при небольшой конкуретности особой нет, можно пользовать и то и другое, к тому же объем критической секции почти всегда нивелирует разницу в производительности между этими блокировками.

Ок! спасибо! Буду теперь думать где что применять :)

А вопрос у меня возник , когда наткнулся на такой код singleton :

Код: java
1.
2.
3.
4.
5.
6.
public static synchronized ServiceFactory getInstance() {
        if(instance == null) {
            instance = new ServiceFactory();
        }
        return instance;
    }  



Насколько провисает производительность при получении ссылки на фабрику в многопоточной среде ...

Если фабрика используется в jsp страницах для получения данных.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421621
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Насколько провисает производительность при получении ссылки на фабрику в многопоточной среде ...
Если фабрика используется в jsp страницах для получения данных.
На децл, но провисает. Чем больше юзеров, тем больше задержка. Для сервера не очень хороший код. Че было не взять любой IoC DI контейнер не понятно.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421625
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1 ,
Если не хотите провисать, то сделайте double-checked locking, и вопрос про synchronized/lock отпадет сам собой: http://habrahabr.ru/post/143390/
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421654
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvЕсли не хотите провисать, то сделайте double-checked locking, и вопрос про synchronized/lock отпадет сам собой: http://habrahabr.ru/post/143390/
Я где-то читал что новые гарантии JMM в Java 6 хоть и улучшают ситуацию с DCL, но не исправляют её окончательно.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421655
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv Atum1 ,
Если не хотите провисать, то сделайте double-checked locking, и вопрос про synchronized/lock отпадет сам собой: http://habrahabr.ru/post/143390/
DCL не нужен, если использовать ленивость Java через дополнительный Holder класс.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38421710
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczЯ где-то читал что новые гарантии JMM в Java 6 хоть и улучшают ситуацию с DCL, но не исправляют её окончательно.
DCL не нужен, если использовать ленивость Java через дополнительный Holder класс.По приведенной выше ссылке оба эти вопроса рассматриваются в деталях. Классический DCL работает через synchronized + volatile начиная с 5.0.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38423726
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvBlazkowiczЯ где-то читал что новые гарантии JMM в Java 6 хоть и улучшают ситуацию с DCL, но не исправляют её окончательно.
DCL не нужен, если использовать ленивость Java через дополнительный Holder класс.По приведенной выше ссылке оба эти вопроса рассматриваются в деталях. Классический DCL работает через synchronized + volatile начиная с 5.0.

собственно секция synchronized для singleton при получении ссылки и не нужна .
Как мне кажется компилятор должен ее убрать через какое то количество циклов , если он умный .
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38423935
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1собственно секция synchronized для singleton при получении ссылки и не нужна .
Как мне кажется компилятор должен ее убрать через какое то количество циклов , если он умный .Не совсем понял, что вы имеете ввиду. Если вы про классический double-checked locking, то там используется связка volatile + synchronized. Да, после инициализации мы не будем приходить в ветку с synchronized, но компилятор не сможет ее выкинуть, так как не сможет заоптимизировать первую проверку на null, ибо она идет по volatile полю.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38424088
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Господа не поясните тупому, а нужен ли volatile при DCL если проверку развернуть на противоположную?
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38424095
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевГоспода не поясните тупому, а нужен ли volatile при DCL если проверку развернуть на противоположную?
Код покажи. Многопоточное создание экземпляра как отработает?
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38424096
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей Арсеньев,

хотя да нужен, может ведь не весь адрес записаться
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38435619
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Самый показательный результат дает AtomicInteger

При N= 100000000 и 10 потоках он рвет и synchronized и обходит lock()


Код: java
1.
2.
3.
4.
5.
public static AtomicInteger iCounter = new AtomicInteger(0);

    public static int getInstance() {
        return iCounter.incrementAndGet();
    }



Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
lock.lock() 
100000000
Time spent: 5.434246025 sec

syninc 
100000000
Time spent: 21.641281703 sec

AtomicReference 
100000000
Time spent: 3.083562757 sec
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38435646
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Самый показательный результат дает AtomicInteger
Открыл глаза. Google -> CAS -> Lock Free, etc

Atum1При N= 100000000 и 10 потоках он рвет и synchronized и обходит lock()

Потому что CAS это не блокировка. А Lock и synchronized - это блокировка.


Atum1lock.lock() - 5.434246025 sec
syninc - 21.641281703 sec
AtomicReference - 3.083562757 sec

Тест меряет максимальную нагрузку на лок - идет постоянная конкуренция. Только в этом случае Lock дает значительные выигрышь перед synchronized. Т.е. это единственный критерий. Надобность в такой блокировке возникает не часто. А если она возникает часто, то можно подумать над тем как реализовать то же самое без критической секции вообще.
В то же время при низкой конкуренкции synchronized может выдать лучшую производительность за счет Biased Locking или просто такую же как RL.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38435677
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь вопрос как правильно написать Singleton через AtomicReference , так чтобы он возвращал еще быстрее , можно создать пул который будет пополняться экземплярами класса Singleton - и забираться по AtomicReference при вызове.

Пример :

Есть сервлет - в котором есть ссылка на сonfig - это Map<String, String> ключ значение .

Эта мапа обновляется очень редко, но при каждом запросе пользователя мы берем из нее данные для генерации страницы :

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
 
@Repository
public class SiteConfigSeriveImpl extends implements SiteConfigSerive{
private ConcurrentMap<String, String> сonfig;

    @Override
    public SiteKeyConfig save(SiteKeyConfig cfg) {
        cfg = super.save(cfg);
        load();
        return cfg;
    }

   @Transactional
    public void load() {
        ConcurrentMap<String, String>  tmp= new ConcurrentHashMap<String, String>();
        DetachedCriteria detachedCriteria //  запрос на заполнение 
        List<SiteKeyConfig> siteKeyConfigs =  getByCriteria(detachedCriteria, 0, 100);
        for (SiteKeyConfig siteKeyConfig : siteKeyConfigs) {
           tmp.put(siteKeyConfig.getKey(),siteKeyConfig.getValue());
       }
       this.сonfig = tmp;
    }


    @Override
    public Map<String, String> getConfig() {
        return сonfig ;
    }



код сервлета :

Код: java
1.
2.
3.
4.
5.
 @Autowired
  private SiteConfigSerive siteConfig;
...
 String str = siteConfig.getConfig().get("key1");
...



т.е. в Местах обращения к siteConfig.getConfig() и получения ссылки на единственный экземпляр ConcurrentMap<String, String> мы будем иметь конкуренцию

За ссылку siteConfig ???

чтобы ее снять какие действия нам нужно предпринять ?

Добавить в класс SiteConfigSeriveImpl pool из AtomicReference из ConcurrentMap<String, String> сonfig; которые мы будем постоянно насыщать ... и отдавать при запросах ?
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38435683
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Теперь вопрос как правильно написать Singleton через AtomicReference , так чтобы он возвращал еще быстрее , можно создать пул который будет пополняться экземплярами класса Singleton - и забираться по AtomicReference при вызове.

http://www.rsdn.ru/forum/java/4473617
http://stackoverflow.com/questions/5938163/singleton-using-atomicreference
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436016
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz http://www.rsdn.ru/forum/java/4473617
http://stackoverflow.com/questions/5938163/singleton-using-atomicreference

Может я не прав, но пример по первой ссылке даже без конкуренции вызовет конструктор два раза, а в условиях оной даже больше. Если конструктор не прописывает созданный экземпляр в каком-нибудь списке то просто лишняя работа.

Во втором случае можно получить не полностью инициализированный instance.

И оно того стоит?
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436020
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сергей АрсеньевИ оно того стоит?
Дык и я о том же.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436802
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ваш тест некорректен по следующим причинам (включая, но наверняка не ограничиваясь ими):

- переменная counter не используется, т.е., компилятор имеет право выбросить ее, а значит и выбросить циклы. И он это сделает, как только поймет это. Спасет ли чтение волатильной переменной (условие i < N в цикле for), если цикл пустой? Хз, точно сказать не могу.

- нет гарантии, что потоки выполняются параллельно. Система имеет полное право отработать так: сначала отрабатывает 1 и завершается поток, потом второй и тд. При этом видимость одновременного доступа есть, но по факту доступ последовательный, а это значит что кешлайн не гуляет между ядрами, и вы не нарываетесь на такую штуку как flase sharing (в данном случае это корректней обозвать true sharing потому что переменная одна, но механизм тот же). А раз вы на нее не нарываетесь, то примерно раз в 20...100 оно будет работать быстрей.

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

таким образом вы померяли неверно. У вас что-то померялось, но не то.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436919
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хм... AtomicInteger реализован как вызовы класса Unsafe.
Возможно синхронизация этих сущностей вынесена
из JVM во вне для скорости.

Код: java
1.
2.
3.
4.
public static sun.misc.Unsafe getUnsafe();
public native long objectFieldOffset(java.lang.reflect.Field field);
public native void putOrderedInt(java.lang.Object o, long l, int i);
public final native boolean compareAndSwapInt(java.lang.Object o, long l, int i, int i1);
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436925
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton, ты ли это?
Atomic реализованы на CAS на уровне команд процессора. Естественно никакой Java API для этого не используется. Только натив.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38436981
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Это я. И это просто рассуждения вслух. Просто разбираясь с оптимизацией перформанса
полезно знать стек. Тоесть что чего вызывает и что от чего зависит. ТС-у полезно также
знать что механизмы синхронизации Java построенные на других механизмах Java вряд-ли
дадут ему особый прирост скорости.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38438953
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokваш тест некорректен по следующим причинам (включая, но наверняка не ограничиваясь ими):

- переменная counter не используется, т.е., компилятор имеет право выбросить ее, а значит и выбросить циклы. И он это сделает, как только поймет это. Спасет ли чтение волатильной переменной (условие i < N в цикле for), если цикл пустой? Хз, точно сказать не могу.




Жду от вас корректного теста и результатов :)
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38438984
cdtyjv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Жду от вас корректного теста и результатов :)Коллега, вы совершенно зря язвите. Вы будете удивлены, но написать качественный многопоточный бенчмарк какого-нибудь реального сценария, в котором есть СУБД, сокеты, работа с файловой системой, и прочие прелести, в разы проще , чем написать качественный бенчмарк, который измерит какой-нибудь volatile vs non-volatile или synchronized vs ReentrantLock. Еще раз акцентирую ваше внимание: в разы проще .
Это как в физике. Когда вы рассматриваете тела макроскопически, то это обычная материя, к которой применимы, например, законы Ньютона. Но когда вы спускаетесь на квантовый уровень, вы сразу же начинаете охреневать от неопределенности Гейзенберга, корпусклуярно-волнового Дуализма и прочих "прелестей". В микромире законы маркомира не работают. Микромир значительно сложнее.
И Java тут не является исключением. Если хотите лучше понимать, что происходит на таких уровнях, то рекомендую вам сделать следующее:
1) Почитать Java Concurreny in Practice - для разгона
2) Почитать The Art of Multiprocessor Programming - что бы понимать, как создавали классы из java.util.concurrent, тут уже ягодки идут
3) Почитать папИр Дага Ли, в котором он рассказывает, как создавался AbstractQueueSynchronzer: http://gee.cs.oswego.edu/dl/papers/aqs.pdf
4) Подписаться на мэилинг-лист concurrency-interest
5) Посмотреть презенташки по многопоточности из JUG.RU: http://vk.com/jugru
6) Почитать и пощупать Шипилевский JMH.

Вот когда сделаете это, тогда и будете здесь подстебывать мемберов, и пытаться брать их "на слабо". А сейчас "слабо" вам, так что лучше не отвергать предлагаемую помощь, и слушать советы.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38438991
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjv,
обычно уже на 3-4 пункте начинаешь осознавать свою неполноценность:)
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38438997
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvМикромир значительно сложнееПроще. Но от этого не легче.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38439010
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cdtyjvВот когда сделаете это, тогда и будете здесь подстебывать мемберов, и пытаться брать их "на слабо". А сейчас "слабо" вам, так что лучше не отвергать предлагаемую помощь, и слушать советы.

Да я и не подстебывал .

все замечания описанные выше имеют место быть.

А так же опираясь на Ваш тезис о микромире - можно сказать след. А что мешает :

А) переменная counter не используется - а может и используется. или сделать простую проверку чтобы она использовалась.
Б) нет гарантии, что потоки выполняются параллельно - но и нет опровержения.
В) для работы снхронизедов надо, чтобы чтобы компилятор собрал профиль и откомпилил код - если добавить более четкие параметры для кода - получим точно такую же ситуацию - исходя из пунктов А и Б.

Это JAVAAAA (c) - тут вообще нет честных тестов :)
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38439972
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,
От меня корректного теста не будет, по той причине что я сам пока не знаю как это померять.
Когда-то скачивал jmh - и не понял его. Документировано там все слабовато, и есть самоисключающие примеры. Самоисключающие - это когда результаты теста противоречат сами себе. Так и не понял, как им пользоваться. Верней, как пользоваться ясно, но как правильно написать тест и померять именно то, что я хочу - неясно.

И судя по тому как вы злитесь, подстебнули не вы меня, а я вас. :) Сам меряю производительность так: пишутся варианты реальной программы и ей подсовываю данные близкие к реальным. На микроуровне я уже понял, что тестить что-то бесполезно.

Насчет используется/не используется тоже не все так очевидно. На самом деле, использовать переменную просто - выводим ее на печать.
Только такое использование спасет от оптимизации "выбрасывания", но не спасет от оптимизации анролинга циклов, например. А просто использование проверкой тоже может быть оптимизировано, если оно не несет смысловой нагрузки.

> Б) нет гарантии, что потоки выполняются параллельно - но и нет опровержения.
вот я и говорю - мы меряем непонятно что.
из личных практических наблюдеий - если есть 10 потоков, то эти потоки по факту стартуют не в той последовательности как их запускаешь в цикле.
Следовательно, как минимум, часть инкрементов была выполнена без реальной конкуренции за данные, а значит и завершение потоков было не одновременным на сколько-то. Это с высокой вероятностью можно предполагать.

ps. Посмотрите исходники ReentrantLock, может накопаете чего интересного.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38439982
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokОт меня корректного теста не будет, по той причине что я сам пока не знаю как это померять.

Что-то ты перемудрил. И так везде пишут что при высокрой нагруженности ReentrantLock более производительный чем synchronized, что тест выше и показал. Но в реальности это ничего не даёт. Так как подобная конкуренция встречается не часто. А при низкой конкурентности synchronized покажет лучшие результаты.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38442798
chabapok
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,

Я не перемудрил, я привык критически смотреть на то, что пишут в интернете, выборочно проверяя (в том числе с целью самообучения) некоторые утверждения. Да, ReentrantLock, да пишут. Но как повторить самому это дома - я незнаю, о чем и сообщил.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38444721
Сергей Арсеньев
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chabapokНо как повторить самому это дома -

Ну создаешь
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
class Incrementer{

 private long value=-1l;

 public long synchronized inc() {
  return (++value);
 }

}



Массивчик на 1000 инкрементеров. И два потока которые много раз пробегают по массиву (в разные стороны) и вызывают inc().

И тоже самое через Lock.

Встречаться они должны не часто - вот и низкая конкуренция.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671049
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Возник такой вопрос : а как построить самый быстрый счетчик - инкремент ,
который будет безопасно работать многопоточной среде ?

что то есть быстрее AtomicInteger ?
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671052
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1Возник такой вопрос : а как построить самый быстрый счетчик - инкремент ,
который будет безопасно работать многопоточной среде ?

что то есть быстрее AtomicInteger ?
Есть. Каждому потоку выдать по своему счетчику и в конце просуммировать по всем потокам. На сколько я помню, должно быть быстрее AtomicInteger.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671059
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Atum1 , LongAdder.
Основан на другом принципе - инкременты с разных потоков идут в разные переменные, тем самым снижая contention. А когда надо получить сумму - просто проходим по ним, и суммируем. Для точных вычислений он не пригоден, но очень резв.

С другой стороны, начиная с Java7 для CASов стандартных атомиков сделаны интринсики, которые устремляют к нулю количество "обломов" на одновременных CAS-ах с разных потоков, поэтому с выходом Java7 атомики стали заметно шустрее на некоторых платформах, включая наш родной x86.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671063
DEVcoach
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вернее, не для самих CASов, а для некоторых других методов, которые основаны на них. Например, incrementAndGet(), addAndGet() и т.д..
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671068
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О! спасибо!

как раз нашел

https://github.com/takipi/counters-benchmark/tree/master/src/main/java/com/takipi/tests/counters/implementations

и описание :

http://www.takipiblog.com/2014/04/16/java-8-longadders-the-fastest-way-to-add-numbers-concurrently/

видимо не я один такими вопросами задаюсь :)
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671121
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вспомнив, что ускорение на порядок куска кода, занимающего десять процентов общего времени даёт (всего) девять процентов выигрыша, начинаешь прикидывать - стОит ли вообще овчинка выделки?..
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #38671770
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

ну хз.... может в торговых система и имеет :)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
test synchronized vs ReentrantLock
    #39015160
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кто может объяснить на каких операциях будет разница между этими типами :


AtomicInteger vs LongAdder vs LongAccumulator

http://winterbe.com/posts/2015/05/22/java8-concurrency-tutorial-atomic-concurrent-map-examples/

написал тест такого плана - разницу не увидел , почему ?

только от N=10000000 - но там и погрешность есть ...


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.LongAccumulator;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.LongBinaryOperator;
import java.util.stream.IntStream;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

@Warmup(iterations = 5)
@Measurement(iterations = 10)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(2)
public class Sum {

    public static void stop(ExecutorService executor) {
        try {
            executor.shutdown();
            executor.awaitTermination(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            System.err.println("termination interrupted");
        } finally {
            if (!executor.isTerminated()) {
                System.err.println("killing non-finished tasks");
            }
            executor.shutdownNow();
        }
    }

    public static int fori(int n) {

        long sum = 0;
        for (int i = 0; i < n; i++) {
            sum += i;

        }

        return (int) sum;
    }

    public static int longAdder(int n) {
        LongAdder adder = new LongAdder();

        ExecutorService executor = Executors.newFixedThreadPool(4);

        IntStream.range(0, n)
                .forEach(i -> executor.submit(adder::increment));

        stop(executor);

        return adder.intValue();
    }

    public static int atomicInteger(int n) {
        AtomicInteger atomicInt = new AtomicInteger(0);

        ExecutorService executor = Executors.newFixedThreadPool(4);

        IntStream.range(0, n)
                .forEach(i -> executor.submit(atomicInt::incrementAndGet));

        stop(executor);

        return atomicInt.intValue();
    }

    public static int longAccumulator(int n) {

        LongBinaryOperator op = (x, y) -> x + y;

        LongAccumulator accumulator = new LongAccumulator(op, 1L);;

        ExecutorService executor = Executors.newFixedThreadPool(4);

        IntStream.range(0, n)
                .forEach(i -> executor.submit(() -> accumulator.accumulate(i)));

        stop(executor);

        return accumulator.intValue();
    }

    @Param({"1000", "10000", "100000", "1000000", "10000000"})
    private int n;

    @Benchmark
    public void testLongAdder(Blackhole bh) {
        bh.consume(longAdder(n));
    }

    @Benchmark
    public void testAtomicInteger(Blackhole bh) {
        bh.consume(atomicInteger(n));
    }

    @Benchmark
    public void testLongAccumulator(Blackhole bh) {
        bh.consume(longAccumulator(n));
    }
    @Benchmark
    public void testFori(Blackhole bh) {
        bh.consume(fori(n));
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(Sum.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }

}





Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
# Run complete. Total time: 00:07:44

Benchmark                     (n)  Mode  Cnt     Score      Error  Units
Sum.testAtomicInteger        1000  avgt   10     0,536 ±    0,022  ms/op
Sum.testAtomicInteger       10000  avgt   10     2,737 ±    0,087  ms/op
Sum.testAtomicInteger      100000  avgt   10    20,559 ±    1,064  ms/op
Sum.testAtomicInteger     1000000  avgt   10   206,458 ±   18,769  ms/op
Sum.testAtomicInteger    10000000  avgt   10  5101,871 ± 1605,404  ms/op
Sum.testFori                 1000  avgt   10    &#8776; 10&#8315;&#179;             ms/op
Sum.testFori                10000  avgt   10     0,004 ±    0,001  ms/op
Sum.testFori               100000  avgt   10     0,043 ±    0,001  ms/op
Sum.testFori              1000000  avgt   10     0,430 ±    0,010  ms/op
Sum.testFori             10000000  avgt   10     4,281 ±    0,018  ms/op
Sum.testLongAccumulator      1000  avgt   10     0,524 ±    0,013  ms/op
Sum.testLongAccumulator     10000  avgt   10     2,540 ±    0,064  ms/op
Sum.testLongAccumulator    100000  avgt   10    19,878 ±    1,078  ms/op
Sum.testLongAccumulator   1000000  avgt   10   210,660 ±    9,564  ms/op
Sum.testLongAccumulator  10000000  avgt   10  3238,301 ±  400,139  ms/op
Sum.testLongAdder            1000  avgt   10     0,539 ±    0,039  ms/op
Sum.testLongAdder           10000  avgt   10     2,655 ±    0,097  ms/op
Sum.testLongAdder          100000  avgt   10    21,172 ±    0,839  ms/op
Sum.testLongAdder         1000000  avgt   10   215,976 ±   16,169  ms/op
Sum.testLongAdder        10000000  avgt   10  3712,276 ± 1076,237  ms/op
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #39015962
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,

Разницы не видно из-за того, что бенчамарк тестирует не счетчики, а создание и остановку потоков.
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #39016830
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
schwaAtum1,

Разницы не видно из-за того, что бенчамарк тестирует не счетчики, а создание и остановку потоков.


???
...
Рейтинг: 0 / 0
test synchronized vs ReentrantLock
    #39017236
Фотография schwa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
 @Benchmark
    public void testLongAdder(Blackhole bh) {
        LongAdder adder = new LongAdder();

        ExecutorService executor = Executors.newFixedThreadPool(4); // 1

        IntStream.range(0, n)
                .forEach(i -> executor.submit(adder::increment)); // 2

        stop(executor); // 3

       bh.consume(accumulator.longValue();
}


Что делает этот код?
1 - создать 4 потока
2 - выполнить какой-то код в 4 потоках
3 - остановить потоки

Шаги 1 и 3 в сумме съедают больше времени, чем суммирование счетчиков.
Из-за того, что у вашем бенчмарке фиксированное число потоков (при этом очень маленькое), вы иногируете тот факт, что классы LongAdder и LongAccumulator разработаны для совершенно иной ситуации - когда потоков много и они соревнуются между собой за одну единствунную ячейку памяти.

Вот результат бенчмарка, запущенного на n1-standard x16 CPU виртуалке на Google Compute Engine
Код: html
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
# Run complete. Total time: 00:04:22

Benchmark                         Mode  Cnt          Score         Error  Units
CountersBenchmark.al_x02         thrpt   10   45135864.893 ? 1185034.673  ops/s
CountersBenchmark.al_x04         thrpt   10   38169882.884 ?   51139.952  ops/s
CountersBenchmark.al_x08         thrpt   10   37985227.786 ?  131890.714  ops/s
CountersBenchmark.al_x16         thrpt   10   52128402.365 ?  240725.555  ops/s
CountersBenchmark.al_x32         thrpt   10   64183053.929 ?  322331.204  ops/s
CountersBenchmark.al_x64         thrpt   10   56510534.133 ?  485246.626  ops/s
CountersBenchmark.longAdder_x02  thrpt   10  175008499.380 ?  487533.370  ops/s
CountersBenchmark.longAdder_x04  thrpt   10  342938648.209 ? 1248616.682  ops/s
CountersBenchmark.longAdder_x08  thrpt   10  491676490.764 ? 6343110.926  ops/s
CountersBenchmark.longAdder_x16  thrpt   10  492169577.462 ? 2963772.754  ops/s
CountersBenchmark.longAdder_x32  thrpt   10  494638487.463 ? 3466056.114  ops/s
CountersBenchmark.longAdder_x64  thrpt   10  496521481.868 ? 4182585.045  ops/s



Характеристики виртуалки

$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 8
On-line CPU(s) list: 0-7
Thread(s) per core: 2
Core(s) per socket: 4
Socket(s): 1
NUMA node(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 45
Model name: Intel(R) Xeon(R) CPU @ 2.60GHz
Stepping: 7
CPU MHz: 2600.000
BogoMIPS: 5200.00
Hypervisor vendor: KVM
Virtualization type: full
L1d cache: 32K
L1i cache: 32K
L2 cache: 256K
L3 cache: 20480K
NUMA node0 CPU(s): 0-7


Сам бенчмарк, не претендует на идеал, но по крайней мере здесь всеми потоками рулит JMH и, следовательно, числа в итогом отчете содержат минимум шума. Можно запустить побольше форков и поиграться со счетчиком в цикле, но отличия в производительности уже и так есть (что не удивительно).


java -jar target/benchmarks.jar -wi 10 -i 10 -f 1

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
package playground;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.infra.Blackhole;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

public class CountersBenchmark {

    @State(Scope.Benchmark)
    public static class LongA {

        final LongAdder adder = new LongAdder();
    }

    @State(Scope.Benchmark)
    public static class AtomicL {

        final AtomicLong aLong = new AtomicLong();
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(2)
    public void al_x02(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(4)
    public void al_x04(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(8)
    public void al_x08(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(16)
    public void al_x16(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(32)
    public void al_x32(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(64)
    public void al_x64(AtomicL a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(2)
    public void longAdder_x02(LongA a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(4)
    public void longAdder_x04(LongA a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(8)
    public void longAdder_x08(LongA a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(16)
    public void longAdder_x16(LongA a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(32)
    public void longAdder_x32(LongA a, Blackhole bh) {
        add(a, bh);
    }

    @Benchmark
    @OperationsPerInvocation(1000)
    @Threads(64)
    public void longAdder_x64(LongA a, Blackhole bh) {
        add(a, bh);
    }

    private void add(LongA a, Blackhole bh) {
        for (int i = 0; i < 1000; i ++) {
            a.adder.increment();
        }
        bh.consume(a.adder.longValue());
    }

    private void add(AtomicL a, Blackhole bh) {
        for (int i = 0; i < 1000; i ++) {
            a.aLong.incrementAndGet();
        }
        bh.consume(a.aLong.longValue());
    }
}


...
Рейтинг: 0 / 0
49 сообщений из 49, показаны все 2 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / test synchronized vs ReentrantLock
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]