热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

各种同步方法性能比较(synchronized,ReentrantLock,Atomic)

为什么80%的码农都做不了架构师?为了比较一下ReentrantLock和synchronized的性能,做了一下性能测试:得出结论

为什么80%的码农都做不了架构师?>>>   hot3.png

为了比较一下ReentrantLock和synchronized的性能,做了一下性能测试:

得出结论:

(1)使用Lock的性能比使用synchronized关键字要提高4~5倍;

(2)使用信号量实现同步的速度大约比synchronized要慢10~20%;

(3)使用atomic包的AtomicInter速度是比Lock要快1一个数量级。

ReentrantLock 类
java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现。这就为 Lock 的多种实现留下了空间,各种实现可能有不同的调度算法、性能特性或者锁定语义。ReentrantLock 类实现了 Lock,它拥有与 synchronized 相同的并发性和内存语义,但是添加了类似锁投票、定时锁等候和可中断锁等候的一些特性。此外,它还提供了在激烈争用情况下更佳的性能。(换句话说,当许多线程都想访问共享资源时,JVM 可以花更少的时候来调度线程,把更多时间用在执行线程上。)

reentrant 锁意味着什么呢?简单来说,它有一个与锁相关的获取计数器,如果拥有锁的某个线程再次得到锁,那么获取计数器就加1,然后锁需要被释放两次才能获得真正释放。这模仿了 synchronized 的语义;如果线程进入由线程已经拥有的监控器保护的 synchronized 块,就允许线程继续进行,当线程退出第二个(或者后续)synchronized 块的时候,不释放锁,只有线程退出它进入的监控器保护的第一个 synchronized 块时,才释放锁。

在查看清单 1 中的代码示例时,可以看到 Lock 和 synchronized 有一点明显的区别 —— lock 必须在 finally 块中释放。否则,如果受保护的代码将抛出异常,锁就有可能永远得不到释放!这一点区别看起来可能没什么,但是实际上,它极为重要。忘记在 finally 块中释放锁,可能会在程序中留下一个定时bomb,当有一天bomb爆炸时,您要花费很大力气才有找到源头在哪。而使用同步,JVM 将确保锁会获得自动释放。

  Test的源码

view plaincopy to clipboardprint?
01.public abstract class Test {  
02.    protected String id;  
03.    protected CyclicBarrier barrier;  
04.    protected long count;  
05.    protected int threadNum;  
06.    protected ExecutorService executor;  
07. 
08.    public Test(String id, CyclicBarrier barrier, long count, int threadNum,  
09.            ExecutorService executor) {  
10.        this.id = id;  
11.        this.barrier = barrier;  
12.        this.count = count;  
13.        this.threadNum = threadNum;  
14.        this.executor = executor;  
15.    }  
16. 
17.    public void startTest() {  
18. 
19.        long start = System.currentTimeMillis();  
20. 
21.        for (int j = 0; j 22.            executor.execute(new Thread() {  
23.                @Override 
24.                public void run() {  
25.                    for (int i = 0; i 26.                        test();  
27.                    }  
28. 
29.                    try {  
30.                        barrier.await();  
31. 
32.                    } catch (InterruptedException e) {  
33.                        e.printStackTrace();  
34.                    } catch (BrokenBarrierException e) {  
35.                        e.printStackTrace();  
36.                    }  
37.                }  
38.            });  
39.        }  
40. 
41.        try {  
42.            barrier.await();  
43.        } catch (InterruptedException e) {  
44.            e.printStackTrace();  
45.        } catch (BrokenBarrierException e) {  
46.            e.printStackTrace();  
47.        }  
48. 
49.        // 所有线程执行完成之后,才会跑到这一步  
50.        long duration = System.currentTimeMillis() - start;  
51.        System.out.println(id + " = " + duration);  
52.    }  
53. 
54.    protected abstract void test();  
55.} 
public abstract class Test {
 protected String id;
 protected CyclicBarrier barrier;
 protected long count;
 protected int threadNum;
 protected ExecutorService executor;

 public Test(String id, CyclicBarrier barrier, long count, int threadNum,
   ExecutorService executor) {
  this.id = id;
  this.barrier = barrier;
  this.count = count;
  this.threadNum = threadNum;
  this.executor = executor;
 }

 public void startTest() {

  long start = System.currentTimeMillis();

  for (int j = 0; j    executor.execute(new Thread() {
    @Override
    public void run() {
     for (int i = 0; i       test();
     }

     try {
      barrier.await();

     } catch (InterruptedException e) {
      e.printStackTrace();
     } catch (BrokenBarrierException e) {
      e.printStackTrace();
     }
    }
   });
  }

  try {
   barrier.await();
  } catch (InterruptedException e) {
   e.printStackTrace();
  } catch (BrokenBarrierException e) {
   e.printStackTrace();
  }

  // 所有线程执行完成之后,才会跑到这一步
  long duration = System.currentTimeMillis() - start;
  System.out.println(id + " = " + duration);
 }

 protected abstract void test();
}
 

测试类ReentreLockTest 源码

 
view plaincopy to clipboardprint?
01.import thread.test.Test;  
02. 
03.public class ReentreLockTest {  
04.    private static long COUNT = 1000000;  
05.    private static Lock lock = new ReentrantLock();  
06.    private static long lockCounter = 0;  
07.    private static long syncCounter = 0;  
08.    private static long semaCounter = 0;  
09.    private static AtomicLong atomicCounter = new AtomicLong(0);  
10.    private static Object syncLock = new Object();  
11.    private static Semaphore mutex = new Semaphore(1);  
12. 
13.    public static void testLock(int num, int threadCount) {  
14. 
15.    }  
16. 
17.    static long getLock() {  
18.        lock.lock();  
19.        try {  
20.            return lockCounter;  
21.        } finally {  
22.            lock.unlock();  
23.        }  
24.    }  
25. 
26.    static long getSync() {  
27.        synchronized (syncLock) {  
28.            return syncCounter;  
29.        }  
30.    }  
31. 
32.    static long getAtom() {  
33.        return atomicCounter.get();  
34.    }  
35. 
36.    static long getSemaphore() throws InterruptedException {  
37.        mutex.acquire();  
38. 
39.        try {  
40.            return semaCounter;  
41.        } finally {  
42.            mutex.release();  
43.        }  
44.    }  
45. 
46.    static long getLockInc() {  
47.        lock.lock();  
48.        try {  
49.            return ++lockCounter;  
50.        } finally {  
51.            lock.unlock();  
52.        }  
53.    }  
54. 
55.    static long getSyncInc() {  
56.        synchronized (syncLock) {  
57.            return ++syncCounter;  
58.        }  
59.    }  
60. 
61.    static long getAtomInc() {  
62.        return atomicCounter.getAndIncrement();  
63.    }  
64. 
65.    static class SemaTest extends Test {  
66. 
67.        public SemaTest(String id, CyclicBarrier barrier, long count,  
68.                int threadNum, ExecutorService executor) {  
69.            super(id, barrier, count, threadNum, executor);  
70.        }  
71. 
72.        @Override 
73.        protected void test() {  
74.            try {  
75.                getSemaphore();  
76.            } catch (InterruptedException e) {  
77.                e.printStackTrace();  
78.            }  
79.        }  
80. 
81.    }  
82. 
83.    static class LockTest extends Test {  
84. 
85.        public LockTest(String id, CyclicBarrier barrier, long count,  
86.                int threadNum, ExecutorService executor) {  
87.            super(id, barrier, count, threadNum, executor);  
88.        }  
89. 
90.        @Override 
91.        protected void test() {  
92.            getLock();  
93.        }  
94. 
95.    }  
96. 
97.    static class SyncTest extends Test {  
98. 
99.        public SyncTest(String id, CyclicBarrier barrier, long count,  
100.                int threadNum, ExecutorService executor) {  
101.            super(id, barrier, count, threadNum, executor);  
102.        }  
103. 
104.        @Override 
105.        protected void test() {  
106.            getSync();  
107.        }  
108. 
109.    }  
110. 
111.    static class AtomicTest extends Test {  
112. 
113.        public AtomicTest(String id, CyclicBarrier barrier, long count,  
114.                int threadNum, ExecutorService executor) {  
115.            super(id, barrier, count, threadNum, executor);  
116.        }  
117. 
118.        @Override 
119.        protected void test() {  
120.            getAtom();  
121.        }  
122. 
123.    }  
124. 
125.    public static void test(String id, long count, int threadNum,  
126.            ExecutorService executor) {  
127. 
128.        final CyclicBarrier barrier = new CyclicBarrier(threadNum + 1,  
129.                new Thread() {  
130. 
131.                    @Override 
132.                    public void run() {  
133. 
134.                    }  
135.                });  
136. 
137.        System.out.println("==============================");  
138.        System.out.println("count = " + count + "\t" + "Thread Count = " 
139.                + threadNum);  
140. 
141.        new LockTest("Lock ", barrier, COUNT, threadNum, executor).startTest();  
142.        new SyncTest("Sync ", barrier, COUNT, threadNum, executor).startTest();  
143.        new AtomicTest("Atom ", barrier, COUNT, threadNum, executor)  
144.                .startTest();  
145.        new SemaTest("Sema ", barrier, COUNT, threadNum, executor)  
146.                .startTest();  
147.        System.out.println("==============================");  
148.    }  
149. 
150.    public static void main(String[] args) {  
151.        for (int i &#61; 1; i <5; i&#43;&#43;) {  
152.            ExecutorService executor &#61; Executors.newFixedThreadPool(10 * i);  
153.            test("", COUNT * i, 10 * i, executor);  
154.        }  
155.    }  
156.} 
import thread.test.Test;

public class ReentreLockTest {
 private static long COUNT &#61; 1000000;
 private static Lock lock &#61; new ReentrantLock();
 private static long lockCounter &#61; 0;
 private static long syncCounter &#61; 0;
 private static long semaCounter &#61; 0;
 private static AtomicLong atomicCounter &#61; new AtomicLong(0);
 private static Object syncLock &#61; new Object();
 private static Semaphore mutex &#61; new Semaphore(1);

 public static void testLock(int num, int threadCount) {

 }

 static long getLock() {
  lock.lock();
  try {
   return lockCounter;
  } finally {
   lock.unlock();
  }
 }

 static long getSync() {
  synchronized (syncLock) {
   return syncCounter;
  }
 }

 static long getAtom() {
  return atomicCounter.get();
 }

 static long getSemaphore() throws InterruptedException {
  mutex.acquire();

  try {
   return semaCounter;
  } finally {
   mutex.release();
  }
 }

 static long getLockInc() {
  lock.lock();
  try {
   return &#43;&#43;lockCounter;
  } finally {
   lock.unlock();
  }
 }

 static long getSyncInc() {
  synchronized (syncLock) {
   return &#43;&#43;syncCounter;
  }
 }

 static long getAtomInc() {
  return atomicCounter.getAndIncrement();
 }

 static class SemaTest extends Test {

  public SemaTest(String id, CyclicBarrier barrier, long count,
    int threadNum, ExecutorService executor) {
   super(id, barrier, count, threadNum, executor);
  }

  &#64;Override
  protected void test() {
   try {
    getSemaphore();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }

 }

 static class LockTest extends Test {

  public LockTest(String id, CyclicBarrier barrier, long count,
    int threadNum, ExecutorService executor) {
   super(id, barrier, count, threadNum, executor);
  }

  &#64;Override
  protected void test() {
   getLock();
  }

 }

 static class SyncTest extends Test {

  public SyncTest(String id, CyclicBarrier barrier, long count,
    int threadNum, ExecutorService executor) {
   super(id, barrier, count, threadNum, executor);
  }

  &#64;Override
  protected void test() {
   getSync();
  }

 }

 static class AtomicTest extends Test {

  public AtomicTest(String id, CyclicBarrier barrier, long count,
    int threadNum, ExecutorService executor) {
   super(id, barrier, count, threadNum, executor);
  }

  &#64;Override
  protected void test() {
   getAtom();
  }

 }

 public static void test(String id, long count, int threadNum,
   ExecutorService executor) {

  final CyclicBarrier barrier &#61; new CyclicBarrier(threadNum &#43; 1,
    new Thread() {

     &#64;Override
     public void run() {

     }
    });

  System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");
  System.out.println("count &#61; " &#43; count &#43; "\t" &#43; "Thread Count &#61; "
    &#43; threadNum);

  new LockTest("Lock ", barrier, COUNT, threadNum, executor).startTest();
  new SyncTest("Sync ", barrier, COUNT, threadNum, executor).startTest();
  new AtomicTest("Atom ", barrier, COUNT, threadNum, executor)
    .startTest();
  new SemaTest("Sema ", barrier, COUNT, threadNum, executor)
    .startTest();
  System.out.println("&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");
 }

 public static void main(String[] args) {
  for (int i &#61; 1; i <5; i&#43;&#43;) {
   ExecutorService executor &#61; Executors.newFixedThreadPool(10 * i);
   test("", COUNT * i, 10 * i, executor);
  }
 }
}
 

结果

view plaincopy to clipboardprint?
01.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
02.count &#61; 1000000 Thread Count &#61; 10  
03.Lock  &#61; 953  
04.Sync  &#61; 3781  
05.Atom  &#61; 78  
06.Sema  &#61; 4922  
07.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
08.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
09.count &#61; 2000000 Thread Count &#61; 20  
10.Lock  &#61; 1906  
11.Sync  &#61; 8469  
12.Atom  &#61; 172  
13.Sema  &#61; 9719  
14.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
15.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
16.count &#61; 3000000 Thread Count &#61; 30  
17.Lock  &#61; 2890  
18.Sync  &#61; 12641  
19.Atom  &#61; 219  
20.Sema  &#61; 15015  
21.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
22.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;  
23.count &#61; 4000000 Thread Count &#61; 40  
24.Lock  &#61; 3844  
25.Sync  &#61; 17141  
26.Atom  &#61; 343  
27.Sema  &#61; 19782  
28.&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;


转载于:https://my.oschina.net/digerl/blog/33282


推荐阅读
  • 1Lock与ReadWriteLock1.1LockpublicinterfaceLock{voidlock();voidlockInterruptibl ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 深入理解Java虚拟机的并发编程与性能优化
    本文主要介绍了Java内存模型与线程的相关概念,探讨了并发编程在服务端应用中的重要性。同时,介绍了Java语言和虚拟机提供的工具,帮助开发人员处理并发方面的问题,提高程序的并发能力和性能优化。文章指出,充分利用计算机处理器的能力和协调线程之间的并发操作是提高服务端程序性能的关键。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Android工程师面试准备及设计模式使用场景
    本文介绍了Android工程师面试准备的经验,包括面试流程和重点准备内容。同时,还介绍了建造者模式的使用场景,以及在Android开发中的具体应用。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • linux进阶50——无锁CAS
    1.概念比较并交换(compareandswap,CAS),是原⼦操作的⼀种,可⽤于在多线程编程中实现不被打断的数据交换操作࿰ ... [详细]
author-avatar
昀尧约_146
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有