位置: 建议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. codeforces 399B. Red and Blue Balls 解题报告

    题目链接:http://codeforces.com/problemset/problem/399/B 题目意思:给出 n 个只由 R 和 B 组成的字符串(由上到下排列,相当于栈),问最多可以操作多 ...

  2. phpstudy开启时mysql不开启时红色灯

    1.本身为开启 2.mysql服务没有启动

  3. 在canvas标签和style中定义width和height

    在canvas标签中定义width.height跟在style中定义width.height是不同的.canvas标签的width和height是画布实际宽度和高度,就是在这个上面绘制图形.style ...

  4. LA-4356&&hdu-2469 (极角排序+扫描线)

    题目链接: Fire-Control System Time Limit: 12000/5000 MS (Java/Others)     Memory Limit: 32768/32768 K (J ...

  5. codeforces 696C C. PLEASE(概率+快速幂)

    题目链接: C. PLEASE time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  6. SpringMVC实现ajax文件上传

    SpringMVC实现文件上传,直接上代码: 后台代码: 01 @RequestMapping(value = "/uploadApk") 02 @ResponseBody 03 ...

  7. JAVA 中 synchronized 详解

    看到一篇关于JAVA中synchronized的用法的详解,觉得不错遂转载之..... 原文地址: http://www.cnblogs.com/GnagWang/archive/2011/02/27 ...

  8. 877C

    构造 想了好长时间... 答案是n+n/2 我们这么想,先把偶数位置炸一遍,所有坦克都在奇数位置,然后再把奇数炸一遍,坦克都到偶数去了,然后再炸一次偶数就都炸掉了... 好巧妙啊 奇偶讨论很重要 #i ...

  9. Linux2.6 内核中结构体初始化(转载)

    转自:http://hnniyan123.blog.chinaunix.net/uid-29917301-id-4989879.html 在Linux2.6版本的内核中,我们经常可以看到下面的结构体的 ...

  10. 由mysql分区想到的分表分库的方案

    在分区分库分表前一定要了解分区分库分表的动机. 对实时性要求比较高的场景,使用数据库的分区分表分库. 对实时性要求不高的场景,可以考虑使用索引库(es/solr)或者大数据hadoop平台来解决(如数 ...