位置: 建议127: Lock与synchronized是不一样的

首先在概念上纠正这一篇内容:

援引Java源码中关于ReentrantLock的开篇说明:

* A reentrant mutual exclusion {@link Lock} with the same basic
 * behavior and semantics as the implicit monitor lock accessed using
 * {@code synchronized} methods and statements, but with extended
 * capabilities.

根据说明: 两个加锁方式是具有相同的基础行为和语义的,仅仅是表现形式上和功能扩展性方面的差别,所以该建议理论是错误的.

以下代码段的执行差异和原作者的解释错误主要出现在以下几个方面:

1.  ReentrantLock和synchronized 都是对象级所,而没有一个是类级的,因此都只能作用到代码所影响的具体对象上去.

  如 synchronized public void read(){

    // some executing code region

  } 其实是隐式锁定了this;

  等价于:

  Lock lock = new ReentrantLock();

  public void read(){

    lock.lock();

    try{

      // some executing code region

    }finally{

      lock.unlock();

    }

  }

  两者的区别是一个monitorthis, 一个monitor lock对象.

比较特殊的情况是:

synchronized publi static execute(){

  

}

该类对象锁定的是 .class对象.

下文中的不一致性主要出现在对"A"的synchronized锁定上,

常量字符串对象在整个生命周期内是全局唯一的,因此,对"A"的所是全局生效的,不仅仅在次类内部,及时全局任何对synchronized("A")都会产生同步效果,这里违反了封闭原则,因此具有巨大的编程风险.

援引代码错误:

该篇引用了两段代码来说明两种方式的行为不一致性.

在这里简单地列举并指出问题所在:

class1 : lock

/*****************************************************************************/

class Task {

  public void doSomething(){

    try{

      Thread.sleep(2000);

    }catch(Exception e){

      // 异常处理

    }

    StringBuilder sb = new StringBuilder();

    // 线程名称:

    sb.append(" 线程名称: " + Thread.currentThread().getName());

    // 运行时间戳

    sb.append(",执行时间: " + Calendar.getInstance().get(13) + " s");

    System.out.println(sb.toString());

  }

}

/****************************************************************************/

class TaskWithLock extends Task implements Runnable{

  private final Lock lock = new ReentrantLock();

  @Override

  public void run(){

    try{

      // 开始锁定

      lock.lock();

      doSomething();

    }finally{

      // 释放锁

      lock.unlock();

    }

  }

}

/***************************************************************************/

class TaskWithSync extends Task implements Runnable{

  @Override

  public void run(){

    // 内部索

    synchronized("A"){

      doSomething();

    }

  }

}

public static void runTasks(Class<? extends Runnable> clazz) throws Exception {

  try{

  ExecutorService es = Executors.newCachedThreadPool();

  System.out.println("***开始执行" + clazz.getSimpleName() + " 任务已执行完毕-----------------\n");

  // 启动三个线程

  for ( int i=0; i<3 ; i++){

    es.submit(clazz.newInstance());

  }

  TimeUnit.SECONDS.sleep(10);

  System.out.println("--------" + clazz.getSimpleName() + " 任务执行完毕------\n");

  // 关闭执行器

  }finally{

    es.shutdown();

  }

}

秦晓波著的编写高质量代码-改善Java程序的151个建议一书中的线程解释错误.的更多相关文章

  1. 编写高质量代码改善java程序的151个建议——[1-3]基础?亦是基础

    原创地址:   http://www.cnblogs.com/Alandre/  (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks The reasonable man adapts himse ...

  2. 博友的 编写高质量代码 改善java程序的151个建议

    编写高质量代码 改善java程序的151个建议 http://www.cnblogs.com/selene/category/876189.html

  3. 编写高质量代码改善java程序的151个建议——导航开篇

    2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...

  4. 编写高质量代码:改善Java程序的151个建议 --[117~128]

    编写高质量代码:改善Java程序的151个建议 --[117~128] Thread 不推荐覆写start方法 先看下Thread源码: public synchronized void start( ...

  5. 编写高质量代码:改善Java程序的151个建议 --[106~117]

    编写高质量代码:改善Java程序的151个建议 --[106~117] 动态代理可以使代理模式更加灵活 interface Subject { // 定义一个方法 public void reques ...

  6. 编写高质量代码:改善Java程序的151个建议 --[78~92]

    编写高质量代码:改善Java程序的151个建议 --[78~92] HashMap中的hashCode应避免冲突 多线程使用Vector或HashTable Vector是ArrayList的多线程版 ...

  7. 编写高质量代码:改善Java程序的151个建议 --[65~78]

    编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...

  8. 编写高质量代码:改善Java程序的151个建议 --[52~64]

    编写高质量代码:改善Java程序的151个建议 --[52~64] 推荐使用String直接量赋值 Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String字符串是程序 ...

  9. 编写高质量代码:改善Java程序的151个建议 --[36~51]

    编写高质量代码:改善Java程序的151个建议 --[36~51] 工具类不可实例化 工具类的方法和属性都是静态的,不需要生成实例即可访 问,而且JDK也做了很好的处理,由于不希望被初始化,于是就设置 ...

随机推荐

  1. IntelliJ IDEA 注册码 有效期截止于2018/10/14

    来源: http://idea.lanyus.com/ IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW ...

  2. Javascript中两种最通用的定义类的方法

    在Javascript中,一切都是对象,包括函数.在Javascript中并没有真正的类,不能像C#,PHP等语言中用 class xxx来定义.但Javascript中提供了一种折中的方案:把对象定 ...

  3. [Java] 读取文件

    1.按字节读取文件内容2.按字符读取文件内容3.按行读取文件内容 4.随机读取文件内容 public class ReadFromFile { /** * 以字节为单位读取文件,常用于读二进制文件,如 ...

  4. H5页面解决左右滑动问题

    在head里面加入. <meta name="viewport" content="width=device-width, initial-scale=1.0, u ...

  5. Watir 能够为你做什么?

    为了提高自己的工作效率,我曾经对Watir进行了系统性的学习,比起学习C++, Java等始终不得门,Watir还是学进去了,能够完整搭建出一个自己很容易理解的自动化架构. 之后我想继续在自动化测试方 ...

  6. python(二):使用multiprocessing中的常见问题

    简介在python的解释器中,CPython是应用范围最广的一种,其具有丰富的扩展包,方便了开发者的使用.当然CPython也不是完美的,由于全局解释锁(GIL)的存在,python的多线程可以近似看 ...

  7. cmake官方文档

    https://cmake.org/cmake/help/v3.0/genindex.html

  8. Bootstrap-CSS:排版

    ylbtech-Bootstrap-CSS:排版 1.返回顶部 1. Bootstrap 排版 Bootstrap 使用 Helvetica Neue. Helvetica. Arial 和 sans ...

  9. ASP.NET Core:WebAppCoreAngular

    ylbtech-ASP.NET Core:WebAppCoreAngular 1.返回顶部 1. 2. 3. 4. 5. 6. 2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部   ...

  10. Unity脚本打包android工程

    using UnityEngine; using System.Collections; using UnityEditor; public class NewBehaviourScript : Ed ...