一、什么是sychronized

sychronized是java中最基本同步互斥的手段,可以修饰代码块,方法,类.

在修饰代码块的时候需要一个reference对象作为锁的对象.

在修饰方法的时候默认是当前对象作为锁的对象.

在修饰类时候默认是当前类的Class对象作为锁的对象.

synchronized会在进入同步块的前后分别形成monitorenter和monitorexit字节码指令.在执行monitorenter指令时会尝试获取对象的锁,如果此没对象没有被锁,或者此对象已经被当前线程锁住,那么锁的计数器加一,每当monitorexit被锁的对象的计数器减一.直到为0就释放该对象的锁.由此synchronized是可重入的,不会出现自己把自己锁死.

二、什么ReentrantLock

以对象的方式来操作对象锁.相对于sychronized需要在finally中去释放锁。

三、synchronized和ReentrantLock的区别

1. 等待可中断

在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待.   tryLock(long timeout, TimeUnit unit)。

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的是非公平锁,ReentrantLock可以通过构造函数实现公平锁.    new RenentrantLock(boolean fair)

3.绑定多个Condition

通过多次newCondition可以获得多个Condition对象,可以简单的实现比较复杂的线程同步的功能.通过await(),signal()

此外,synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将 unLock()放到finally{} 中。在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态。

四、实例演示

ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。比如:如果A、B两个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候ReentrantLock就提供了两种机制:

一、B线程中断自己(或者别的线程中断它),但ReentrantLock 不去响应,让B线程继续等待,你再怎么中断,我全当耳边风(synchronized原语就是如此);

二、B线程中断自己(或者别的线程中断它),ReentrantLock 处理了这个中断,并且不再等待这个锁的到来,完全放弃。

请看例子:

[html] view plain copy

  1. package zmx.multithread.test.reentrantlock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. /**
  4. *
  5. * @author zhangwenchao
  6. *
  7. */
  8. public class ReentrantLockTest {
  9. //是用ReentrantLock,还是用synchronized
  10. public static boolean useSynchronized = false;
  11. public static void main(String[] args) {
  12. IBuffer buff = null;
  13. if(useSynchronized){
  14. buff = new Buffer();
  15. }else{
  16. buff = new BufferInterruptibly();
  17. }
  18. final Writer writer = new Writer(buff);
  19. final Reader reader = new Reader(buff);
  20. writer.start();
  21. reader.start();
  22. new Thread(new Runnable() {
  23. public void run() {
  24. long start = System.currentTimeMillis();
  25. for (;;) {
  26. // 等5秒钟去中断读
  27. if (System.currentTimeMillis() - start > 5000) {
  28. System.out.println("不等了,尝试中断");
  29. reader.interrupt();
  30. break;
  31. }
  32. }
  33. }
  34. }).start();
  35. }
  36. }
  37. interface IBuffer{
  38. public void write();
  39. public void read() throws InterruptedException;
  40. }
  41. class Buffer implements IBuffer{
  42. private Object lock;
  43. public Buffer() {
  44. lock = this;
  45. }
  46. public void write() {
  47. synchronized (lock) {
  48. long startTime = System.currentTimeMillis();
  49. System.out.println("开始往这个buff写入数据…");
  50. for (;;)// 模拟要处理很长时间
  51. {
  52. if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
  53. break;
  54. }
  55. System.out.println("终于写完了");
  56. }
  57. }
  58. public void read() {
  59. synchronized (lock) {
  60. System.out.println("从这个buff读数据");
  61. }
  62. }
  63. }
  64. class BufferInterruptibly implements IBuffer{
  65. private ReentrantLock lock = new ReentrantLock();
  66. public void write() {
  67. lock.lock();
  68. try {
  69. long startTime = System.currentTimeMillis();
  70. System.out.println("开始往这个buff写入数据…");
  71. for (;;)// 模拟要处理很长时间
  72. {
  73. if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
  74. break;
  75. }
  76. System.out.println("终于写完了");
  77. } finally {
  78. lock.unlock();
  79. }
  80. }
  81. public void read() throws InterruptedException{
  82. lock.lockInterruptibly();// 注意这里,可以响应中断
  83. // lock.lock();// 注意这里,不可以响应中断
  84. try {
  85. System.out.println("从这个buff读数据");
  86. } finally {
  87. lock.unlock();
  88. }
  89. }
  90. }
  91. class Writer extends Thread {
  92. private IBuffer buff;
  93. public Writer(IBuffer buff) {
  94. this.buff = buff;
  95. }
  96. @Override
  97. public void run() {
  98. buff.write();
  99. }
  100. }
  101. class Reader extends Thread {
  102. private IBuffer buff;
  103. public Reader(IBuffer buff) {
  104. this.buff = buff;
  105. }
  106. @Override
  107. public void run() {
  108. try {
  109. buff.read();
  110. } catch (InterruptedException e) {
  111. System.out.println("我不读了");
  112. }
  113. System.out.println("读结束");
  114. }
  115. }

1) 如果使用lock.lockInterruptibly();指定可以响应中断,则输出如下:

[html] view plain copy

  1. 开始往这个buff写入数据…
  2. 不等了,尝试中断
  3. 我不读了
  4. 读结束

则:获取到中断异常,执行中断异常处理程序。

2) 如果使用lock.lock();指定不可以响应中断,则输出如下:

[html] view plain copy

  1. 开始往这个buff写入数据…
  2. 不等了,尝试中断

则:不能获取到中断异常,线程等待。

示例二:

[html] view plain copy

  1. package zmx.multithread.test.reentrantlock;
  2. import java.util.concurrent.TimeUnit;
  3. import java.util.concurrent.locks.Lock;
  4. import java.util.concurrent.locks.ReentrantLock;
  5. public class T2{
  6. public static void main(String[] args){
  7. Thread i1 = new Thread(new RunIt3());
  8. Thread i2 = new Thread(new RunIt3());
  9. i1.start();
  10. i2.start();
  11. i2.interrupt();  //中断
  12. }
  13. }
  14. class RunIt3 implements Runnable{
  15. private static Lock lock = new ReentrantLock();
  16. public void run(){
  17. try{
  18. //---------a--------------------------
  19. //lock.lock();
  20. lock.lockInterruptibly();
  21. //lock.tryLock();
  22. //lock.tryLock(5,TimeUnit.SECONDS);
  23. System.out.println(Thread.currentThread().getName() + " running");
  24. TimeUnit.SECONDS.sleep(10);
  25. System.out.println(Thread.currentThread().getName() + " finished");
  26. lock.unlock();
  27. }catch (InterruptedException e){
  28. System.out.println(Thread.currentThread().getName() + " interrupted");
  29. }
  30. }
  31. }

如果a处是lock.lock(); 输出: 
Thread-0 running 
(这里休眠了10s) 
Thread-0 finished 
Thread-1 running 
Thread-1 interrupted 
============================ 
    如果a处是lock.lockInterruptibly();输出: 
Thread-0 running 
Thread-1 interrupted 
(这里休眠了10s) 
Thread-0 finished

synchronized和ReentrantLock区别浅析 (转载地址:http://blog.csdn.net/zmx729618/article/details/51594166)相关推荐

  1. 从request获取各种路径总结 转载:http://blog.csdn.net/piaoxuan1987/article/details/8541839 equest.getRealPath()

    https://www.cnblogs.com/hello-yao-ge/p/6606564.html 转载:http://blog.csdn.net/piaoxuan1987/article/det ...

  2. WordPress数据库的基本构造(转载自http://blog.csdn.net/ppiao1970hank/article/details/6301812)...

    转载自http://blog.csdn.net/ppiao1970hank/article/details/6301812 WordPress使用MySQL数据库.作为一个开发者,我们有必要掌握Wor ...

  3. Android Volley完全解析(二),使用Volley加载网络图片 转载:http://blog.csdn.net/guolin_blog/article/details/174

    转载:http://blog.csdn.net/guolin_blog/article/details/17482165 在上一篇文章中,我们了解了Volley到底是什么,以及它的基本用法.本篇文章中 ...

  4. 手机网络抓包 转载记录http://blog.csdn.net/skylin19840101/article/details/43485911

    Fiddler不但能截获各种浏览器发出的HTTP请求, 也可以截获各种智能手机发出的HTTP/HTTPS请求.Fiddler能捕获IOS设备发出的请求,比如IPhone, IPad, MacBook. ...

  5. solr教程,值得刚接触搜索开发人员一看(转载:http://blog.csdn.net/awj3584/article/details/16963525)

    Solr调研总结 开发类型 全文检索相关开发 Solr版本 4.2 文件内容 本文介绍solr的功能使用及相关注意事项;主要包括以下内容:环境搭建及调试;两个核心配置文件介绍;维护索引;查询索引,和在 ...

  6. 架构之路之spring+springmvc+maven+mongodb的搭建(转载:http://blog.csdn.net/tomcat_2014/article/details/55100130)

    1.前言 最近项目开发使用到了spring+springmvc+maven+MongoDB,项目中的框架是用springboot进项开发的,对于我们中级开发人员来说,有利有弊,好处呢是springbo ...

  7. JSFL元件类型判断 转载于 https://blog.csdn.net/linking530/article/details/8364600

    //获取舞台上第一层第一帧上的全部元件 var els = fl.getDocumentDOM().getTimeline().layers[0].frames[0].elements; //遍历元件 ...

  8. linux未知的类型名 FILE,smb使用 ------转载自http://blog.csdn.net/tlaff/article/details/5463068...

    一.在Linux系统中查看网络中Windows共享文件及Linux中的Samba共享文件: 常用到smbclient:用法如下 [root@localhost ~]# smbclient  -L  / ...

  9. 排序算法汇总——转载自http://blog.csdn.net/zhanglong_daniel/article/details/52513058

    1. 冒泡排序 1.1 算法原理: S1:从待排序序列的起始位置开始,从前往后依次比较各个位置和其后一位置的大小并执行S2. S2:如果当前位置的值大于其后一位置的值,就把他俩的值交换(完成一次全序列 ...

最新文章

  1. php linux 调试工具,内网Visual Studio Code通过XDebug远程调试linux服务器PHP脚本
  2. mysql的limit优化_mysql数据库limit优化例子(百万级数据)
  3. 借钱合同有哪些陷阱?
  4. Spark入门(九)之PI估值
  5. 1b8c语言,C语言 - 王朝网络 - wangchao.net.cn
  6. Maven包装过程中跳过测试
  7. java structs hibernate php_eclipse+hibernate+structs 环境搭建
  8. vuex辅助函数和vuex5个属性
  9. python网络爬虫系列教程——Python+PhantomJS +Selenium组合应用
  10. 深度学习推荐模型-DeepFM
  11. 暑假学习日记2013/8/20
  12. 魔改Dual Thrust示例策略
  13. 当“双态IT”已成共识 如何打造以数据驱动的运维平台?
  14. 测试睡眠质量软件,2018测睡眠质量的app排行榜:推荐10款有趣又有效的睡眠APP
  15. 生物信息学入门 富集分析与蛋白质互作用网络(PPI)的可视化 Cystocape入门指南
  16. mysql 申花球队面试题_mysql面试题练习01
  17. 解决win10下 Virtual Box USB功能无法使用问题
  18. Java基础5多线程技术
  19. 武林外传私服服务器制作,自己修改的YY朱武林外传服务端+架设工具+完整补丁...
  20. 算法学习之狄克斯特拉算法

热门文章

  1. [墨者安全]解析2019年国内DDOS第一季度报告
  2. iOS10 越狱, openSSH
  3. 【示波器专题】示波器触发电路原理
  4. android app bundle Split APKs
  5. JavaScript走向成熟
  6. 【Unity--头顶UI 人物头顶UI】特别简单的实现人物头顶UI显示跟随
  7. 国内的网站咋这么难看呢
  8. springboot 之 自动生成接口文档工具JApiDocs
  9. 生产制造业管理软件如何帮助企业做好售后服务管理?
  10. 【arduino库文件】-wire.h