- 浏览: 518974 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (161)
- 多线程与并发编程 (20)
- 算法和数据结构 (8)
- 缓存 (0)
- HttpClient (2)
- 疑难杂症 (11)
- Java内存管理 (17)
- 分布式开发 (14)
- Linux常用命令 (10)
- OSGI (0)
- UML (2)
- 趣味面试题 (5)
- 设计模式 (8)
- Java类加载 (2)
- JSTL (1)
- Web 服务器 (4)
- IT人生 (3)
- Java基础 (11)
- Flash技术 (7)
- 新知识 (3)
- 常用速备速查 (4)
- 版本控制 (1)
- Java集合工具类 (6)
- web前端技术 (1)
- 趣味话题 (1)
- 安全 (0)
- 架构设计 (5)
- Spring (4)
- 负载均衡技术 (2)
- 持久层技术 (2)
- MySQL单机多实例方案 (1)
- 收藏备用 (0)
- 性能优化 (3)
最新评论
-
liuwuhen:
...
Pushlet的工作原理 -
fbwfbi:
fengchuizhuming 写道楼主的完全正确。鉴定完毕楼 ...
硬件同步原语(CAS)理论 -
passerby_whu:
uule 写道这个测试后结果为:“testPageConten ...
FutureTask的使用方法和使用实例 -
fengchuizhuming:
楼主的完全正确。鉴定完毕
硬件同步原语(CAS)理论 -
edwardjuice:
FutureTask的使用方法和使用实例
Java 并发编程基础 - 共享对象
目录
1. 可见性
在没有同步的情况下,编译器,处理器,运行时安排操作的执行顺序可能完全出人意料,在没有进行适当同步的多线程程序中,尝试推断哪些“必要”发生在内存中的动作是,你总是会判断错误。
Public class NoVisibility{
Private static boolean ready;
Private static int number;
Private static class ReaderThread extends Thread{
Public void run(){
While(!ready)
Thread.yield();
System.out.println(number);
}
}
Public static void main(String[] args){
New ReaderThread().start();
Number = 42;
Ready = true;
}
}
因为没有进行适当的同步, ready 的值为 true ,对读线程来说, ready 的值可能永远不可见,甚至 NoVisibility 可能会打印出 0. 因为早在对 number 赋值之前,主线程就已经写入 ready 并使之对读线程可见,这是一种“重排序 (Reordering) ”现象。
详见关于重排序的说明。
1.1 过期数据
当一个线程调用 set ,另外一个线程调用 get ,读线程和可能得到一个过期的数据:
@NotThreadSafe
Public class MutableInteger{
Private int value;
Public int get(){ return value; }
Public void set(int value){ this.value=value; }
}
通过 Java 的同步机制,可以保证可见性,保证强的一致性(可以立即看到更新后的结果)
@ThreadSafe
Public class MutableInteger{
Private int value;
Public synchronized int get(){ return value; }
Public synchronized void set(int value){this.value=value;}
}
1.2 非原子的 64 位操作
Java 存储模型要求获取和存储操作都为原子的,但是对于非 volatile 的 long 和 double 变量, JVM 允许将 64 位的读或写划分为两个 32 位操作。如果读和写发生在不同的线程,这种情况读取了一个非 volatile 类型 long 就可能得到一个值的高 32 位和另一个值的低 32 位。
1.3 Volatile 变量是有代价的
现代处理器的发展,让 CPU 的处理能力得到了质的飞跃,这一切都与 cpu 的高速缓存有关系,这就是为什么 Java 内存模型里面,为什么各自线程有自己的工作内存的原因了,另外也由于直接操作主存,需要耗费更多的 CPU 时钟周期,但是如果存在线程安全问题, volatile 不会使用运行线程所在的 CPU 里面的缓存来读取和写输入, volatile 直接操作的是主存。因此实际上, volatile 为了保全可见性,也牺牲了很多性能。
2. 发布和逸出
发布 一个对象指的是使它能够被当前范围之外的代码所使用。比如讲一个引用存储到其他代码可以访问的地方,在一个非私有的方法中返回这个引用,也可以把它传递给其它的方法。
逸出 指的是一个对象在尚未准备好时就将他发布。
不正确的发布对象 - 范围逸出:任何一个调用者都可以修改他的内容,在下例中,数组逸出了它所属的范围。这个本应该是私有的数据,事实上已经变成公有的了。
Public class UnsafeStates{
Private String[] states = new String[]{“AK”,”AL”,...;
Public String[] getStates(){return states;}
}
不正确的发布对象 -This 引用在构造时逸出,当对象并没有完全构造好就被新线程使用。
Public class ThisEscape{
Public ThisEscape(){
New Thread(){
Public void run(){
doSomething();
doSomething1();
}
}).start();
}
注意对象只有通过构造函数返回后,才处于可预言的、稳定的状态,所以从构造函数内部发布的对象只是一个未完成构造的对象。甚至即使是在构造函数的最后一行发布的引用也是如此。
3. 线程封闭
3.1 栈限制
栈限制是线程限制的一种特例,在栈限制中,只能通过本地变量才可以触及对象,本地变量使对象更容易被限制在线程本地中。本地变量本身就被限制在执行线程中;它们存在于执行线程栈。
3.2 ThreadLocal
ThreadLocal 把变量限制在线程内访问,这样两个线程之间不存在共享访问的问题,两个线程各自维护自己的变量。下面的例子说明了,一个原本可以被多线程法访问的变量,经过 ThreadLocal 的改进,变成了只有当前线程才能访问和修改的变量,这样做自然线程就安全了。
public class ThreadLocalImageServlet extends HttpServlet{
public ThreadLocal<String> imageURL = new ThreadLocal<String>(){
public String initialValue(){
return "";
}
};
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
imageURL.set(req.getParameter("imageURL"));
resp.getWriter().println(imageURL.get());
}
}
3.3 不可变性
发表评论
-
死锁实例
2011-05-19 14:21 1903下面这道题,是考死锁的,比较简单,想两个问题: 1.什么时候 ... -
Java存储模型
2011-05-18 13:29 01.什么是存储模型 没有适当的同步,编译器生成指令的次序,可 ... -
设计模式-组合模式
2011-05-16 15:48 1072组合模式的定义: 将对象组合成树的形式来表示整体和局部之 ... -
CompleteService介绍和使用实例
2011-05-11 17:31 3866当向Executor提交批处理任务时,并且希望在它们完成后获得 ... -
CyclicBarrier的使用实例
2011-05-11 15:45 1438CyclicBarrier允许给定数量的线程全部到达关卡点时, ... -
CopyOnWriteArrayList工作原理和实例
2011-05-05 23:43 3340CopyOnWriteArrayList顾名思义,在写入操作时 ... -
Semaphore的介绍和使用实例
2011-04-27 22:32 2768Semaphore可以用来控制能 ... -
FutureTask的使用方法和使用实例
2011-04-27 15:34 13253FutureTask是一种可以取消的异步的计算任务。它的计算是 ... -
CountDownLatch的使用实例
2011-04-26 22:20 8182CountDownLatch CountDownl ... -
从JVM并发看CPU内存指令重排序(Memory Reordering)
2011-04-18 16:17 1445我们都知道,现在的计算机, cpu 在计算的时候 ... -
Java并发编程基础
2011-04-15 14:55 1512Java 并发编程基 ... -
Java多线程基础
2011-04-13 15:52 4698Java 多线程基础 ... 2 ... -
硬件同步原语(CAS)理论
2010-09-24 22:13 6948在Java并发编程中,常常 ... -
java5中使用interrupt()来停止java线程的方法(转)
2010-08-18 23:24 3058在开发java多线程时,如果要停止线程这个问题很头痛吧,不过在 ... -
Java 中的Double Check Lock(转)
2010-07-27 21:13 8042对于多线程编程来说,同步问题是我们需要考虑的最多的问题,同步的 ... -
并发访问的问题解决方案
2010-07-26 18:15 1965目前正在做基于Red 5 的Meeting系统,我们会在Mee ... -
用并发包中的重入锁实现生产消费模型
2010-06-15 00:07 1397传统的生产消费模型,实际上是通过一个条件来调节生产者和消费者线 ... -
ThreadLocal原理(转)
2010-03-24 18:06 2126http://jzhua.iteye.com/blog/517 ... -
(转)Java偏向锁实现原理(Biased Locking)
2010-03-21 22:24 1325http://www.iteye.com/topic/5180 ... -
生产消费模型实例
2010-03-02 23:23 1674“生产者-消费者-仓储”模型,包含三种角色: 1.生产者 ...
相关推荐
使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。
《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...
第3章 对象的共享 3.1 可见性 3.1.1 失效数据 3.1.2 非原子的64位操作 3.1.3 加锁与可见性 3.1.4 Volatile变量 3.2 发布与逸出 3.3 线程封闭 3.3.1 Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3 ThreadLocal类 ...
Java并发编程基础主要包括以下几个核心方面: 线程与线程状态:理解Java中线程的基本概念,包括线程的创建、启动、暂停、恢复和终止。熟悉线程的生命周期及其不同状态,如新建、就绪、运行、阻塞和死亡。 线程同步...
Java并发编程实战,本书从线程的基础知识,包括线程安全性,对象共享以及对象组合灯,到结构化并发编程,都提供了很详细的讲解。
本书的读者是那些具有一定Java编程经验的程序员、希望了解Java SE 5,6在线程技术上的改进和新特性的程序员,以及Java和并发编程的爱好者。 目录 代码清单 序 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的...
第3章 对象的共享 3.1 可见性 3.1.1 失效数据 3.1.2 非原子的64位操作 3.1.3 加锁与可见性 3.1.4 Volatile变量 3.2 发布与逸出 3.3 线程封闭 3.3.1 Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3 ThreadLocal类 3.4...
《java并发编程实战》读书笔记-第3章-对象的共享,脑图形式,使用xmind8制作 包括同步容器类、并发容器类、阻塞队列和生产者消费者模式、阻塞和中断方法、同步工具类。最后是构建高效且可伸缩的结果缓存
通过深入学习,您将建立坚实的并发编程基础,能够更好地理解和应对多线程编程中的挑战。 并发编程概述: 引入并发编程的基本概念,解释为什么多线程编程在现代应用中至关重要。 线程和进程: 解释线程和进程的区别,...
Java并发编程实战,第1章 简介,第2章 线程安全性 第3章 对象的共享 第4章 对象的组合 第5章 基础构建模块 第6章 任务执行 第7章 取消与关闭 第8章 线程池的使用 第9章 图形用户界面应用程序 第10章 避免...
第3章 共享对象 3.1 可见性 3.2 发布和逸出 3.3 线程封闭 3.4 不可变性 3.5 安全发布 . 第4章 组合对象 4.1 设计线程安全的类 4.2 实例限制 4.3 委托线程安全 4.4 向已有的线程安全类添加功能 4.5 同步策略的文档化 ...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
本资源致力于向您介绍 Java 并发编程中的线程基础,涵盖了多线程编程的核心概念、线程的创建和管理,以及线程间通信的基本方法。通过深入学习,您将建立扎实的多线程编程基础,能够更好地理解和应用多线程编程。 多...
java 并发编程实践001 002 两个文件全部下载后 用 7z解压 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 线程的风险 1.4 线程无处不在 第1部分 基础 第2章 线程安全 2.1 什么是线程安全性 2.2 原子...
Java并发编程学些手册,包括并发编程基础、volatile关键字、synchronized关键字、final关键字、对象的共享、同步工具类、线程池、锁、多线程实战等部分的详细介绍和解读。 无论你是面试,还是进阶,这些文章的内容...
中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...
Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...
中文完整版的Java并发编程实践PDF电子书 作者:Brian Gogetz Tim Peierls Joshua Bloch Joseph Bowbeer David Holmes Doug Lea 译者:韩锴 方秒 目录 第1章 介绍 1.1 并发的(非常)简短历史 1.2 线程的优点 1.3 ...