原文:http://www.cnblogs.com/nsw2018/p/5821738.html

1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

ReentrantLock获取锁定与三种方式:
a) lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
c)tryLock(long timeout,TimeUnit unit), 如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的情形下做出正确的选择。

总体的结论先摆出来:

synchronized:
在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。

ReentrantLock:
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

Atomic:
和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。

所以,我们写同步的时候,优先考虑synchronized,如果有特殊需要,再进一步优化。ReentrantLock和Atomic如果用的不好,不仅不能提高性能,还可能带来灾难。

先贴测试结果:再贴代码(Atomic测试代码不准确,一个同步中只能有1个Actomic,这里用了2个,但是这里的测试只看速度)
==========================
round:100000 thread:5
Sync = 35301694
Lock = 56255753
Atom = 43467535
==========================
round:200000 thread:10
Sync = 110514604
Lock = 204235455
Atom = 170535361
==========================
round:300000 thread:15
Sync = 253123791
Lock = 448577123
Atom = 362797227
==========================
round:400000 thread:20
Sync = 16562148262
Lock = 846454786
Atom = 667947183
==========================
round:500000 thread:25
Sync = 26932301731
Lock = 1273354016
Atom = 982564544

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
package test.thread;
import static java.lang.System.out;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class TestSyncMethods {
     
    publicstatic void test(int round,intthreadNum,CyclicBarrier cyclicBarrier){
        newSyncTest("Sync",round,threadNum,cyclicBarrier).testTime();
        newLockTest("Lock",round,threadNum,cyclicBarrier).testTime();
        newAtomicTest("Atom",round,threadNum,cyclicBarrier).testTime();
    }
    publicstatic void main(String args[]){
         
        for(inti=0;i<5;i++){
            intround=100000*(i+1);
            intthreadNum=5*(i+1);
            CyclicBarrier cb=newCyclicBarrier(threadNum*2+1);
            out.println("==========================");
            out.println("round:"+round+" thread:"+threadNum);
            test(round,threadNum,cb);
             
        }
    }
}
class SyncTest extends TestTemplate{
    publicSyncTest(String _id,int_round,int _threadNum,CyclicBarrier _cb){
        super( _id, _round, _threadNum, _cb);
    }
    @Override
    /**
     * synchronized关键字不在方法签名里面,所以不涉及重载问题
     */
    synchronizedlong  getValue() {
        returnsuper.countValue;
    }
    @Override
    synchronizedvoid  sumValue() {
        super.countValue+=preInit[index++%round];
    }
}
class LockTest extends TestTemplate{
    ReentrantLock lock=newReentrantLock();
    publicLockTest(String _id,int_round,int _threadNum,CyclicBarrier _cb){
        super( _id, _round, _threadNum, _cb);
    }
    /**
     * synchronized关键字不在方法签名里面,所以不涉及重载问题
     */
    @Override
    longgetValue() {
        try{
            lock.lock();
            returnsuper.countValue;
        }finally{
            lock.unlock();
        }
    }
    @Override
    voidsumValue() {
        try{
            lock.lock();
            super.countValue+=preInit[index++%round];
        }finally{
            lock.unlock();
        }
    }
}
class AtomicTest extends TestTemplate{
    publicAtomicTest(String _id,int_round,int _threadNum,CyclicBarrier _cb){
        super( _id, _round, _threadNum, _cb);
    }
    @Override
    /**
     * synchronized关键字不在方法签名里面,所以不涉及重载问题
     */
    long getValue() {
        returnsuper.countValueAtmoic.get();
    }
    @Override
    void sumValue() {
        super.countValueAtmoic.addAndGet(super.preInit[indexAtomic.get()%round]);
    }
}
abstractclass TestTemplate{
    privateString id;
    protectedint round;
    privateint threadNum;
    protectedlong countValue;
    protectedAtomicLong countValueAtmoic=newAtomicLong(0);
    protectedint[] preInit;
    protectedint index;
    protectedAtomicInteger indexAtomic=newAtomicInteger(0);
    Random r=newRandom(47);
    //任务栅栏,同批任务,先到达wait的任务挂起,一直等到全部任务到达制定的wait地点后,才能全部唤醒,继续执行
    privateCyclicBarrier cb;
    publicTestTemplate(String _id,int_round,int _threadNum,CyclicBarrier _cb){
        this.id=_id;
        this.round=_round;
        this.threadNum=_threadNum;
        cb=_cb;
        preInit=newint[round];
        for(inti=0;i<preInit.length;i++){
            preInit[i]=r.nextInt(100);
        }
    }
     
    abstractvoid sumValue();
    /*
     * 对long的操作是非原子的,原子操作只针对32位
     * long是64位,底层操作的时候分2个32位读写,因此不是线程安全
     */
    abstractlong getValue();
    publicvoid testTime(){
        ExecutorService se=Executors.newCachedThreadPool();
        longstart=System.nanoTime();
        //同时开启2*ThreadNum个数的读写线程
        for(inti=0;i<threadNum;i++){
            se.execute(newRunnable(){
                publicvoid run() {
                    for(inti=0;i<round;i++){
                        sumValue();
                    }
                    //每个线程执行完同步方法后就等待
                    try{
                        cb.await();
                    }catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
            se.execute(newRunnable(){
                publicvoid run() {
                    getValue();
                    try{
                        //每个线程执行完同步方法后就等待
                        cb.await();
                    }catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }catch (BrokenBarrierException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }
         
        try{
            //当前统计线程也wait,所以CyclicBarrier的初始值是threadNum*2+1
            cb.await();
        }catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (BrokenBarrierException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //所有线程执行完成之后,才会跑到这一步
        longduration=System.nanoTime()-start;
        out.println(id+" = "+duration);
         
    }
}

  

摘自:

http://houlinyan.iteye.com/blog/1112535

http://zzhonghe.iteye.com/blog/826162

Lock与synchronized测试区别相关推荐

  1. Lock与synchronized 的区别

    1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O ...

  2. Java同步锁——lock与synchronized 的区别【转】

    在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...

  3. lock和synchronized的区别

    lock是一个接口,而synchronized是java的一个关键字,synchronized是内置的语言实现:(具体实现上的区别在<Java虚拟机>中有讲解底层的CAS不同,以前有读过现 ...

  4. java多线程:9、synchronized、Lock的底层实现原理以及和volatile、Lock、ReentrantLock的区别?

    文章目录 0.1.线程中安全性问题的体现: 0.2.线程安全问题的解决办法 1.synchronized的底层实现原理分析 2.Lock的底层实现原理分析? 3.synchronized和volati ...

  5. lock与synchronized锁有什么区别?它们的底层实现原理是什么?

    一.共同点 Lock和synchronized都是本地锁,它们都可以通过上锁解决多个线程访问共享资源的问题,并且synchronized和lock锁都支持可重入锁机制,即同一个线程在已经获得锁的情况下 ...

  6. Lock与Synchronized区别

    先说结论,后面详解 synchronized是关键字,Lock是接口; synchronized是隐式的加锁,lock是显式的加锁; synchronized可以作用于方法上,lock只能作用于方法块 ...

  7. Lock和synchronized比较详解

    原文:http://www.cnblogs.com/handsomeye/p/5999362.html 今天看了并发实践这本书的ReentantLock这章,感觉对ReentantLock还是不够熟悉 ...

  8. Java并发编程:Lock和Synchronized 转

    在上一篇文章中我们讲到了如何使用关键字synchronized来实现同步访问.本文我们继续来探讨这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方 ...

  9. Lock接口Condition,以及Lock与synchronized异同

    一.synchronized与Lock 基于synchronized关键字去实现同步的,(jvm内置锁,也叫隐式锁,由我们的jvm自动去加锁跟解锁的)juc下的基于Lock接口的这样的一种锁的实现方式 ...

最新文章

  1. Go 语言编程 — 函数
  2. CentOS 6.3(x86_64)下安装Oracle 10g R2
  3. JavaWeb 错误/异常时页面提示
  4. Android应用程序键盘(Keyboard)消息处理机制分析(3)
  5. 韩文版ie8 启用java_只有在启用了javascript的情况下,IE8才会在IE8模式下重新加载崩溃...
  6. java存储字节,java 数目字转化成字节存储算法
  7. WCF:Maximum number of items that can be serialized or deserialized in an object graph is '65536'.
  8. datax 模板_dataX3.0安装使用手册.docx
  9. 【练习手记】【多题合集】用树状数组做线段树练习1、2、3
  10. 思路与好题记录与小技巧
  11. 常用的Regex验证方法
  12. select获取下拉框的值 下拉框默认选中
  13. 回溯算法 马里奥式学习法
  14. 网站流量分析数据指标
  15. 关于电感元件的反电动势
  16. Excel批量复制选中单元格的整行
  17. 全球45个最热门免费下载电子图书的网站
  18. java导出用什么_Java导出Excel
  19. Kotlin中的also、let、run、with、apply函数的用法
  20. Laravel 的生命周期

热门文章

  1. C语言 游戏远程call调用,C++远程调用类操作支持CallbackInterface(1)
  2. 希尔排序的java算法_Java算法系列篇 【希尔排序】
  3. java stopself_Android Service详解(二)---StartService
  4. mac软件移植linux,相比软件迁移 Apple Silicon Mac的Linux系统移植工作更困难
  5. python如何打开文件编辑界面_Python-PyQt5-图形可视化界面(5)--打开文件或文件夹--QFileDialog...
  6. div中加载html js,Div里面载入另一个页面的实现(Ajax取代框架)
  7. mysql 删除重复索引_如何检查mysql的重复索引
  8. html宽度自适应怎么调整li超出隐藏,HTML篇之CSS样式——div ul li 嵌套后解决高度自适应方法...
  9. 皮一皮:现在流行这样?
  10. 皮一皮:拦着人类进化的原来是酒精?