秦晓波著的编写高质量代码-改善Java程序的151个建议一书中的线程解释错误.
位置: 建议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个建议一书中的线程解释错误.的更多相关文章
- 编写高质量代码改善java程序的151个建议——[1-3]基础?亦是基础
原创地址: http://www.cnblogs.com/Alandre/ (泥沙砖瓦浆木匠),需要转载的,保留下! Thanks The reasonable man adapts himse ...
- 博友的 编写高质量代码 改善java程序的151个建议
编写高质量代码 改善java程序的151个建议 http://www.cnblogs.com/selene/category/876189.html
- 编写高质量代码改善java程序的151个建议——导航开篇
2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...
- 编写高质量代码:改善Java程序的151个建议 --[117~128]
编写高质量代码:改善Java程序的151个建议 --[117~128] Thread 不推荐覆写start方法 先看下Thread源码: public synchronized void start( ...
- 编写高质量代码:改善Java程序的151个建议 --[106~117]
编写高质量代码:改善Java程序的151个建议 --[106~117] 动态代理可以使代理模式更加灵活 interface Subject { // 定义一个方法 public void reques ...
- 编写高质量代码:改善Java程序的151个建议 --[78~92]
编写高质量代码:改善Java程序的151个建议 --[78~92] HashMap中的hashCode应避免冲突 多线程使用Vector或HashTable Vector是ArrayList的多线程版 ...
- 编写高质量代码:改善Java程序的151个建议 --[65~78]
编写高质量代码:改善Java程序的151个建议 --[65~78] 原始类型数组不能作为asList的输入参数,否则会引起程序逻辑混乱. public class Client65 { public ...
- 编写高质量代码:改善Java程序的151个建议 --[52~64]
编写高质量代码:改善Java程序的151个建议 --[52~64] 推荐使用String直接量赋值 Java为了避免在一个系统中大量产生String对象(为什么会大量产生,因为String字符串是程序 ...
- 编写高质量代码:改善Java程序的151个建议 --[36~51]
编写高质量代码:改善Java程序的151个建议 --[36~51] 工具类不可实例化 工具类的方法和属性都是静态的,不需要生成实例即可访 问,而且JDK也做了很好的处理,由于不希望被初始化,于是就设置 ...
随机推荐
- jQuery常用插件大全(9)ResponsiveSlides插件
ResponsiveSlides.js是一个展示同一容器内图片的轻量级响应式jQuery幻灯片插件(tiny responsive slideshow jQuery plugin).它支持包括IE6在 ...
- Burpsuite实验(二)
一.这次我们使用一下burpsuite的代理拦截功能. 图中的proxy是代理的选项,其中intercept是拦截的功能,在浏览器中请求的包,都经过它. 这是打开拦截时候的状态.forward是通过此 ...
- ng 表单提交验证
http://www.runoob.com/try/try.php?filename=try_ng_validate
- Linux下PostgreSQL 的安装与配置
一.简介 PostgreSQL 是一种非常复杂的对象-关系型数据库管理系统(ORDBMS),也是目前功能最强大,特性最丰富和最复杂的自由软件数据库系统.有些特性甚至连商业数据库都不具备.这个起源于伯克 ...
- 035--MySQL基本操作
一.数据库的定义及相关名词解释 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库, 每个数据库都有一个或多个不同的API用于创建,访问,管理,搜索和复制所保存的数据. 我们也可以 ...
- ubuntu的NAT方式上网配置
vm菜单栏虚拟机--->设置---->网络适配器---->勾选NAT方式 vi /etc/network/interfaces修改配置文件如下: auto loiface lo in ...
- CodeForces 718A Efim and Strange Grade (贪心)
题意:给定一个浮点数,让你在时间 t 内,变成一个最大的数,操作只有把某个小数位进行四舍五入,每秒可进行一次. 析:贪心策略就是从小数点开始找第一个大于等于5的,然后进行四舍五入,完成后再看看是不是还 ...
- 51nod 1268【dp】
思路: 很水的dp吧...问的都是能否组成.. 哦对,这里sum最大才2e7,不会是2e9所以放心dp #include<cstdio> #include <map> #inc ...
- lightoj1200 【完全背包】
题意: 有一个能放W重的袋子,然后妻子给了老公一列清单,每个item会有价格,数量,重量. 首先得满足老婆的要求,然后在可装的地方输出最大还能拿多少使得拿的东西的钱最多. 注意标题是thief,我想大 ...
- expect实现配置机器信任关系
利用expect的交互功能,自动配置信任机器之间的信任关系. 代码里会判断机器是否生成了秘钥,如果没有生成过,则自动帮助你执行 ssh-keygen #!/bin/sh expect_ssh_copy ...