`
495081611
  • 浏览: 33122 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

ReentrantLock和synchronized的性能

    博客分类:
  • java
阅读更多
转载 http://my.oschina.net/digerl/blog/33282

为了比较一下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 < threadNum; j++) {  
22.            executor.execute(new Thread() {  
23.                @Override 
24.                public void run() {  
25.                    for (int i = 0; i < count; 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 < threadNum; j++) {
   executor.execute(new Thread() {
    @Override
    public void run() {
     for (int i = 0; i < count; 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 = 1; i < 5; i++) {  
152.            ExecutorService executor = 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 = 1000000;
private static Lock lock = new ReentrantLock();
private static long lockCounter = 0;
private static long syncCounter = 0;
private static long semaCounter = 0;
private static AtomicLong atomicCounter = new AtomicLong(0);
private static Object syncLock = new Object();
private static Semaphore mutex = 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 ++lockCounter;
  } finally {
   lock.unlock();
  }
}

static long getSyncInc() {
  synchronized (syncLock) {
   return ++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);
  }

  @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);
  }

  @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);
  }

  @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);
  }

  @Override
  protected void test() {
   getAtom();
  }

}

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

  final CyclicBarrier barrier = new CyclicBarrier(threadNum + 1,
    new Thread() {

     @Override
     public void run() {

     }
    });

  System.out.println("==============================");
  System.out.println("count = " + count + "\t" + "Thread Count = "
    + 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("==============================");
}

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


结果

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

相关推荐

    ReentrantLock与synchronized

    在Java多线程编程中,`ReentrantLock`和`synchronized`都是用于实现线程同步的重要工具,确保在并发环境中数据的一致性和正确性。两者虽然都能实现互斥访问,但在功能、性能以及使用场景上有所不同。下面我们将深入...

    ReentrantLock 与 synchronized 简介

    ### ReentrantLock 与 synchronized 的比较 #### 一、引言 在Java中,多线程和并发控制一直是程序员关注的重点。随着Java的发展,其语言本身及...通过合理运用这两种工具,可以有效地提高应用程序的并发性能和稳定性。

    深入java并发编程,使用ReentrantLock和 Synchronized加锁

    在Java并发编程中,理解和熟练使用同步机制是至关重要的,这包括了`ReentrantLock`和`synchronized`关键字。这两个工具都是为了确保多线程环境中的数据一致性与安全性,防止出现竞态条件和死锁等问题。 `...

    第15讲 synchronized和ReentrantLock有什么区别呢?1

    在Java编程中,synchronized和ReentrantLock都是用于实现线程同步的重要工具,它们在并发控制方面扮演着关键角色。然而,两者之间存在一些显著的区别,这些差异体现在功能、灵活性、性能以及使用场景上。 首先,...

    简单聊聊Synchronized和ReentrantLock锁.docx

    本文将深入探讨Synchronized关键字锁和ReentrantLock锁的异同、功能特性以及它们在实际应用中的适用场景。 首先,Synchronized是一种内置的Java关键字,它提供了简单而强大的线程同步机制。当一个线程进入一个由...

    22 到底哪把锁更适合你?—synchronized与ReentrantLock对比.pdf

    在Java中,有两种主要的锁机制:内置的`synchronized`关键字和显式的`ReentrantLock`类。这两者各有优劣,适用于不同的场景。下面我们将详细讨论它们的区别、性能、特性以及使用上的差异。 1. **功能对比**: - `...

    Lock、Synchoronized和ReentrantLock的使用

    Lock、Synchronized 和 ReentrantLock 的使用 Lock、Synchronized 和 ReentrantLock 是 Java 中三种常用的同步机制,每种机制都有其特点和使用场景。下面对这三种机制进行详细的分析和比较。 一、Synchronized ...

    java ReentrantLock详解.docx

    `ReentrantLock`是Java并发编程中的一种高级锁机制,它是`java.util.concurrent.locks`包中的类,提供了比`...了解并熟练使用`ReentrantLock`能帮助开发者更好地解决并发问题,提高程序的并发性能和健壮性。

    Java中ReentrantLock的使用.docx

    Java中的ReentrantLock是线程安全编程中的一种高级锁机制,它属于Lock接口的一个实现,提供了比synchronized更丰富的功能和更高的灵活性。ReentrantLock的名字来源于它的可重入性,这意味着一个线程可以多次获取同一...

    ReentrantLock解析

    《ReentrantLock深度解析》 在Java并发编程中,ReentrantLock是JDK提供的一个可...在实际开发中,可以根据需求选择使用synchronized还是ReentrantLock,或者其他的并发控制手段,以达到最佳的并发性能和资源利用效率。

    synchronized关键字的实质及用法

    理解和合理使用`synchronized`能够帮助我们构建稳定、高效的多线程程序,但同时也要注意避免潜在的死锁和性能问题。在实际编程中,应结合具体场景选择`synchronized`或者`ReentrantLock`等同步工具。

    ReentrantLock源码的使用问题详解.docx

    《ReentrantLock源码详解与应用》 ReentrantLock,可重入锁,是Java并发编程中一个重要的锁实现,它提供了比...理解ReentrantLock的源码有助于我们更好地掌握并发编程中的锁机制,以优化并发性能和避免死锁等问题。

    Java synchronized使用案例

    Java中的`synchronized`关键字是多线程编程中的一个重要概念,用于控制并发访问共享资源,以保证数据的一致性和完整性。这个关键词提供了互斥锁机制,防止多个线程同时执行同一段代码,确保了线程安全。 一、`...

    java同步synchronized关键字用法示例

    在Java 5之后,引入了`java.util.concurrent`包,其中的`ReentrantLock`类提供了可重入锁,它具有与`synchronized`相似的功能,但更加灵活,支持公平锁、非公平锁以及可中断的锁等待。 **5. synchronized的应用示例...

    synchronized并发讲解源码.zip

    在实际开发中,合理使用`synchronized`能有效防止数据不一致性和死锁问题,但过度使用可能会导致性能下降。因此,需要根据具体情况权衡其利弊,并考虑使用其他并发控制工具,如`java.util.concurrent`包中的`...

    第15讲synchronized和ReentrantL1

    `synchronized`关键字和`ReentrantLock`是两种常见的同步工具,它们都用于控制并发访问共享资源,以防止数据不一致和线程安全问题。 `synchronized`是Java内建的同步机制,自Java 1.0起就已经存在。它可以修饰方法...

    Java多线程之ReentrantLock与Condition - 平凡希 - 博客园1

    总之,`ReentrantLock`是Java并发编程中的强大工具,它提供了丰富的功能和灵活性,使得开发者能够根据具体需求调整锁的行为,提高并发代码的性能和安全性。在设计和实现多线程程序时,了解和正确使用`ReentrantLock`...

    [JAVA][synchronized的使用]

    在Java编程语言中,`synchronized`关键字是一个至关重要的概念,它主要用于实现线程同步,以确保多线程环境下的数据一致性与...然而,在实际应用中,我们需要根据具体场景选择最合适的并发控制手段,平衡性能和安全性。

    并发编程 70 道面试题及答案.docx

    本文档总结了并发编程中的70道面试题及答案,涵盖了线程、synchronized、volatile、CAS、Lock、ReentrantLock等关键概念,旨在帮助开发者更好地理解并发编程的基本概念和机理。 线程间通信: * wait/notify机制:...

Global site tag (gtag.js) - Google Analytics