关于无锁的线程安全的整数,有以下三种

  • AtomicInteger
  • AtomicLong
  • LongAdder

AtomicInteger

示例

  1. import java.util.concurrent.*;
  2. import java.util.concurrent.atomic.*;
  3. public class AtomicClass {
  4. public static AtomicInteger counter = new AtomicInteger();
  5. public static Integer counter2 = 0;
  6. public static Object mutex = new Object();
  7. public static boolean useLock = false;
  8. public static void main(String[] args) throws InterruptedException {
  9. final Integer Thread_Amount = 20;
  10. //1.创建线程池
  11. ThreadPoolExecutor te = new ThreadPoolExecutor(Thread_Amount,Thread_Amount,0L,TimeUnit.SECONDS,
  12. new LinkedBlockingDeque<>());
  13. //2.创建线程任务
  14. Callable<Long> task = () -> {
  15. long start = System.currentTimeMillis();
  16. if(useLock == false){
  17. for(int k=0; k<100000; k++)
  18. counter.incrementAndGet();
  19. }else{
  20. for(int k=0; k<100000; k++)
  21. synchronized (mutex){
  22. ++counter2;
  23. }
  24. }
  25. long end = System.currentTimeMillis();
  26. return end - start;
  27. };
  28. // 在并发环境下CAS
  29. useLock = false;
  30. {
  31. //3.创建线程
  32. Future<Long>[] futures = new Future[Thread_Amount];
  33. for(int i=0 ; i<Thread_Amount ; i++){
  34. futures[i] = te.submit(task);
  35. }
  36. //4.获得线程结果
  37. long totaltime = 0;
  38. try {
  39. for(int i=0 ; i<Thread_Amount ; i++)
  40. totaltime += futures[i].get();
  41. } catch (ExecutionException e) {
  42. e.printStackTrace();
  43. }
  44. //5.打印结果
  45. System.out.println("当不使用锁时花费时间:" + totaltime + "ms");
  46. }
  47. // 在并发环境下使用锁
  48. useLock = true;
  49. {
  50. //3.创建线程
  51. Future<Long>[] futures = new Future[Thread_Amount];
  52. for(int i=0 ; i<Thread_Amount ; i++){
  53. futures[i] = te.submit(task);
  54. }
  55. //4.获得线程结果
  56. long totaltime = 0;
  57. try {
  58. for(int i=0 ; i<Thread_Amount ; i++)
  59. totaltime += futures[i].get();
  60. } catch (ExecutionException e) {
  61. e.printStackTrace();
  62. }
  63. //5.打印结果
  64. System.out.println("当使用锁时花费时间:" + totaltime + "ms");
  65. }
  66. //7.关闭线程池
  67. te.shutdown();
  68. }
  69. }

console

  1. 当不使用锁时花费时间:413ms
  2. 当使用锁时花费时间:2168ms

将Thread_Amount改为50后的控制台输出:

  1. 当不使用锁时花费时间:723ms
  2. 当使用锁时花费时间:12023ms

可以看出,CAS的性能远高于锁,而且,随着线程数的增加,其性能差距会变得更大。

AtomicLong 与 LongAdder

其中LongAdder是jdk引进的,其性能远高于AtomicLong.

LongAdder的优化:

  • 热点数据的分离(将对一个被频繁访问的数据的操作变成对一个数组的操作,再对数组求和得到应有的数据)
  • 避免了伪共享(避免因其他变量修改而重新加载)

下面的代码可能涉及到高并发模型Future,详见笔记 链接

示例

  1. import java.util.concurrent.*;
  2. import java.util.concurrent.atomic.AtomicLong;
  3. import java.util.concurrent.atomic.LongAdder;
  4. //改注解可以解决伪共享问题
  5. //@sun.misc.Contended
  6. public class LongAdderTest {
  7. static class MyTask implements Callable<Long> {
  8. private static Object mutex = new Object();
  9. private static Long counter = 0L;
  10. private static AtomicLong aCounter = new AtomicLong(0);
  11. private static LongAdder lCounter = new LongAdder();
  12. /**
  13. * state = 0,使用锁进行Long类型的共享
  14. * state = 1,使用AtomicLong
  15. * state = 2, 使用LongAdder
  16. */
  17. private int state = 0;
  18. private static int LIMIT = 10000000;
  19. public MyTask(int state) {
  20. this.state = state;
  21. }
  22. @Override
  23. public Long call() {
  24. long b = 0, e = 0;
  25. if(state == 0){
  26. b = System.currentTimeMillis();
  27. for(int i=0 ; i<LIMIT ; i++){
  28. synchronized (mutex){
  29. ++counter;
  30. }
  31. }
  32. e = System.currentTimeMillis();
  33. }else if(state == 1){
  34. b = System.currentTimeMillis();
  35. for(int i=0 ; i<LIMIT ; i++){
  36. aCounter.incrementAndGet();
  37. }
  38. e = System.currentTimeMillis();
  39. }else if(state == 2){
  40. b = System.currentTimeMillis();
  41. for(int i=0 ; i<LIMIT ; i++){
  42. lCounter.increment();
  43. }
  44. e = System.currentTimeMillis();
  45. }
  46. return e - b;
  47. }
  48. }
  49. public static void main(String[] args) throws ExecutionException, InterruptedException {
  50. ExecutorService ep = Executors.newFixedThreadPool(12);
  51. Future<Long>[] futures = new Future[4];
  52. for(int i=0 ; i<4 ; i++){
  53. futures[i] = ep.submit(new MyTask(0));
  54. }
  55. Future<Long>[] futures2 = new Future[4];
  56. for(int i=0 ; i<4 ; i++){
  57. futures2[i] = ep.submit(new MyTask(1));
  58. }
  59. Future<Long>[] futures3 = new Future[4];
  60. for(int i=0 ; i<4 ; i++){
  61. futures3[i] = ep.submit(new MyTask(2));
  62. }
  63. long time = 0;
  64. for(Future<Long> future : futures){
  65. time += future.get();
  66. }
  67. System.out.println("Long类型花费时间:" + time + "ms");
  68. time = 0;
  69. for(Future<Long> future : futures2){
  70. time += future.get();
  71. }
  72. System.out.println("AtomicLong类型花费时间:" + time + "ms");
  73. time = 0;
  74. for(Future<Long> future : futures3){
  75. time += future.get();
  76. }
  77. System.out.println("LongAdder类型花费时间:" + time + "ms");
  78. ep.shutdown();
  79. }
  80. }

console

  1. Long类型花费时间:10079ms
  2. AtomicLong类型花费时间:3597ms
  3. LongAdder类型花费时间:1278ms