Java 当AtomicInteger比synchronized快时
我已经读过很多文章,其中提到AtomicInteger类比同步构造工作得更快。我在AtomicInteger和“synchronized”上做了一些测试,在我的测试中,synchronized比AtomicInteger快得多。我想了解出了什么问题:我的测试类不正确,或者AtomicInteger在其他情况下工作得更快? 这是我的测试课:Java 当AtomicInteger比synchronized快时,java,concurrency,synchronization,volatile,atomicinteger,Java,Concurrency,Synchronization,Volatile,Atomicinteger,我已经读过很多文章,其中提到AtomicInteger类比同步构造工作得更快。我在AtomicInteger和“synchronized”上做了一些测试,在我的测试中,synchronized比AtomicInteger快得多。我想了解出了什么问题:我的测试类不正确,或者AtomicInteger在其他情况下工作得更快? 这是我的测试课: public class Main { public static void main(String[] args) throws Inte
public class Main {
public static void main(String[] args) throws InterruptedException
{
// creating tester "synchronized" class
TesterSynchronized testSyn = new TesterSynchronized();
// Creating 3 threads
Thread thread1 = new Thread(testSyn);
Thread thread2 = new Thread(testSyn);
Thread thread3 = new Thread(testSyn);
// start time
long beforeSyn = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterSyn = System.currentTimeMillis();
long delta = afterSyn - beforeSyn;
System.out.println("Test synchronized: " + delta + " ms");
// _______________________________________________________
// creating tester "atomicInteger" class
TesterAtomicInteger testAtomic = new TesterAtomicInteger();
thread1 = new Thread(testAtomic);
thread2 = new Thread(testAtomic);
thread3 = new Thread(testAtomic);
// start time
long beforeAtomic = System.currentTimeMillis();
// start
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
long afterAtomic = System.currentTimeMillis();
long deltaAtomic = afterAtomic - beforeAtomic;
System.out.println("Test atomic integer: " + deltaAtomic + " ms");
}
}
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public synchronized void run() {
for (int i = 0; i < 1_000_000; i++)
integerValue++;
}
}
// AtomicInteger class tester
class TesterAtomicInteger implements Runnable {
AtomicInteger atomicInteger = new AtomicInteger(0);
public void run() {
for (int i = 0; i < 1_000_000; i++)
atomicInteger.incrementAndGet();
}
}
公共类主{
公共静态void main(字符串[]args)引发InterruptedException
{
//创建tester“synchronized”类
TesterSynchronized testSyn=新的TesterSynchronized();
//创建3个线程
螺纹螺纹1=新螺纹(testSyn);
螺纹2=新螺纹(testSyn);
螺纹3=新螺纹(testSyn);
//开始时间
long beforeSyn=System.currentTimeMillis();
//开始
thread1.start();
thread2.start();
thread3.start();
thread1.join();
螺纹2.连接();
螺纹3.连接();
long afterSyn=System.currentTimeMillis();
长增量=后同步-前同步;
System.out.println(“测试同步:+delta+“ms”);
// _______________________________________________________
//创建tester“atomicInteger”类
TesterAtomicInteger testAtomic=新的TesterAtomicInteger();
thread1=新线程(testAtomic);
螺纹2=新螺纹(testAtomic);
thread3=新线程(testAtomic);
//开始时间
long beforeaomic=System.currentTimeMillis();
//开始
thread1.start();
thread2.start();
thread3.start();
thread1.join();
螺纹2.连接();
螺纹3.连接();
long afterAtomic=System.currentTimeMillis();
长deltaAtomic=后原子-前原子;
System.out.println(“测试原子整数:“+deltaAtomic+”ms”);
}
}
//同步测试仪
类TesterSynchronized实现可运行{
公共整数整数值=0;
公共同步的无效运行(){
对于(int i=0;i<1_000;i++)
integerValue++;
}
}
//原子整数类测试器
类TesterAtomicIntegrater实现Runnable{
AtomicInteger AtomicInteger=新的AtomicInteger(0);
公开募捐{
对于(int i=0;i<1_000;i++)
atomicInteger.incrementAndGet();
}
}
测试参数:3个线程,增量为1_000_000;
结果:
测试同步:7毫秒。测试原子整数:51毫秒
我很高兴了解为什么会发生这种情况。
UPD
如果将同步方法更改为同步块,则测试将是正确的
//同步测试仪
类TesterSynchronized实现可运行{
公共整数整数值=0;
公开募捐{
对于(int i=0;i<1_000;i++){
已同步(此){
integerValue++;
}
}
}
}
代码中的明显区别在于,AtomicIntger
版本允许线程的交叉访问,而synchronized
版本则依次对每个线程执行整个循环
可能还有其他问题。例如,JVM可以合并一个
同步的块的多个调用。根据平台的不同,incrementAndGet
可能不是一个原子操作,而是作为CAS循环实现的-如果争用很高,这可能是一个问题(我不完全确定)
无论以何种方式排列,如果您有多个线程同时修改同一内存位置,那么速度都不会很快。代码中的明显区别在于,AtomicIntger
版本允许线程交叉访问,而synchronized
版本则依次对每个线程执行整个循环
可能还有其他问题。例如,JVM可以合并一个同步的块的多个调用。根据平台的不同,incrementAndGet
可能不是一个原子操作,而是作为CAS循环实现的-如果争用很高,这可能是一个问题(我不完全确定)
无论采用哪种方式,如果多个线程同时修改同一内存位置,速度都不会很快。在同步测试仪中,您只需锁定一个锁,然后执行百万次增量。在AtomicInteger示例中,您正在为每个增量获取并释放一个锁。尝试将synchronized
包装在integerValue++
周围,AtomicInteger
将更快。你无法比较这两种方法。事实上,这是一个问题!更改为synchronized block后,测试结果为:test synchronized:244 ms test atomic integer:95 ms。除了synchronized
中的错误外,您还应该检查如何执行。在这里的这个测试中,synchronized
可能比较慢,但在其他一些测试中,您希望避免影响结果的噪音。原始的TesterSynchronized循环可以由编译器优化。执行这个循环没有意义;它可以立即将1_000_000分配给integerValue,而不是执行1M增量。在同步测试仪中,您只需执行一个锁,然后执行百万增量。在AtomicInteger示例中,您正在为每个增量获取并释放一个锁。尝试将synchronized
包装在integerValue++
周围,AtomicInteger
将更快。你无法比较这两种方法。事实上,这是一个问题!更改为synchronized block后,测试结果为:test synchronized:244 ms test atomic integer:95 ms。除了synchronized
中的错误外,您还应该检查如何执行。在这里的测试中,可能很清楚
// Synchronized tester
class TesterSynchronized implements Runnable {
public int integerValue = 0;
public void run() {
for (int i = 0; i < 1_000_000; i++) {
synchronized (this) {
integerValue++;
}
}
}
}