- 浏览: 525209 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (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 1938下面这道题,是考死锁的,比较简单,想两个问题: 1.什么时候 ... -
Java存储模型
2011-05-18 13:29 01.什么是存储模型 没有适当的同步,编译器生成指令的次序,可 ... -
设计模式-组合模式
2011-05-16 15:48 1098组合模式的定义: 将对象组合成树的形式来表示整体和局部之 ... -
CompleteService介绍和使用实例
2011-05-11 17:31 3975当向Executor提交批处理任务时,并且希望在它们完成后获得 ... -
CyclicBarrier的使用实例
2011-05-11 15:45 1476CyclicBarrier允许给定数量的线程全部到达关卡点时, ... -
CopyOnWriteArrayList工作原理和实例
2011-05-05 23:43 3380CopyOnWriteArrayList顾名思义,在写入操作时 ... -
Semaphore的介绍和使用实例
2011-04-27 22:32 2806Semaphore可以用来控制能 ... -
FutureTask的使用方法和使用实例
2011-04-27 15:34 13310FutureTask是一种可以取消的异步的计算任务。它的计算是 ... -
CountDownLatch的使用实例
2011-04-26 22:20 8212CountDownLatch CountDownl ... -
从JVM并发看CPU内存指令重排序(Memory Reordering)
2011-04-18 16:17 1478我们都知道,现在的计算机, cpu 在计算的时候 ... -
Java并发编程基础
2011-04-15 14:55 1543Java 并发编程基 ... -
Java多线程基础
2011-04-13 15:52 4733Java 多线程基础 ... 2 ... -
硬件同步原语(CAS)理论
2010-09-24 22:13 6982在Java并发编程中,常常 ... -
java5中使用interrupt()来停止java线程的方法(转)
2010-08-18 23:24 3109在开发java多线程时,如果要停止线程这个问题很头痛吧,不过在 ... -
Java 中的Double Check Lock(转)
2010-07-27 21:13 8090对于多线程编程来说,同步问题是我们需要考虑的最多的问题,同步的 ... -
并发访问的问题解决方案
2010-07-26 18:15 1994目前正在做基于Red 5 的Meeting系统,我们会在Mee ... -
用并发包中的重入锁实现生产消费模型
2010-06-15 00:07 1429传统的生产消费模型,实际上是通过一个条件来调节生产者和消费者线 ... -
ThreadLocal原理(转)
2010-03-24 18:06 2160http://jzhua.iteye.com/blog/517 ... -
(转)Java偏向锁实现原理(Biased Locking)
2010-03-21 22:24 1361http://www.iteye.com/topic/5180 ... -
生产消费模型实例
2010-03-02 23:23 1708“生产者-消费者-仓储”模型,包含三种角色: 1.生产者 ...
相关推荐
首先,我们来探讨Java并发编程的基础概念。并发是指多个执行单元(线程或进程)在同一时间间隔内同时进行工作。在Java中,我们主要通过线程来实现并发。Java提供了多种创建和管理线程的方法,如Thread类、Runnable...
《Java并发编程实战》这本书是Java开发者深入理解并发编程的重要参考书籍。本书旨在帮助程序员解决在多线程环境中遇到的实际问题,提升系统性能并保证其稳定性。随书源码提供了丰富的示例,让读者能够动手实践,加深...
在Java并发编程中,数据的封装与访问控制、线程安全性的考量、同步机制的使用是重要的基础概念和技巧。以下是从给出的文件内容中提取出的详细知识点: 1. 数据封装与访问控制:确保内部私有数据不被轻易访问,并且...
使用java.util.concurrent类库构造安全的并发应用程序的基础。共享其实就是某一线程的数据改变对其它线程可见,否则就会出现脏数据。
《Java并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。...通过阅读这本书,你可以深入理解Java并发编程的理论和实践,提升你的编程能力,为构建高并发、高性能的系统打下坚实基础。
根据提供的信息,我们可以推断出该资源主要关注的是“Java并发编程实践”的相关内容,并且它是一本高清晰度的PDF电子书。虽然提供的链接部分似乎只是重复的网站地址,我们仍可以根据标题、描述以及标签来生成相关的...
《Java并发编程实战》个人读书笔记,非常详细: 1 简介 2 线程安全性 3 对象的共享 4 对象的组合 5 基础构建模块 6 任务执行 7 取消与关闭 8 线程池的使用 9 图形用户界面应用程序 10 避免活跃性危险 11 性能与可...
### Java并发编程基础 - **并发与并行**:并发是指多个任务在同一时间段内被执行(但不一定同一时刻),而并行则是指多个任务同时执行。理解这两者的区别对于深入学习并发编程至关重要。 - **Java并发机制**:Java...
《Java并发编程1-9章》是一份涵盖了Java并发编程核心知识的资料集合,主要源自博客作者Yishizhu在iteye上的分享。通过阅读这些章节,我们可以深入了解Java平台上的多线程和并发处理机制,这对于任何需要处理高性能、...
总之,《Java并发编程实战》是一本全面介绍Java并发编程的书籍,适合有一定Java基础并希望提升并发编程能力的开发者阅读。通过学习,你可以掌握解决并发问题的策略和技巧,编写出更加健壮和高效的多线程应用。
《Java并发编程实践》这本书是Java开发者...这些知识点构成了Java并发编程的基础,理解和掌握它们对于编写高效、稳定的多线程Java应用程序至关重要。在实际编程中,要根据具体需求灵活应用,并注意性能和安全性的平衡。
在Java并发编程中,线程安全是一个至关重要的概念,它涉及到多线程环境下对共享数据的正确管理和访问。线程安全意味着当多个线程同时访问一个对象或数据时,对象的状态能够保持一致性和完整性,不会因为并发导致数据...
此外,Java并发编程还包括对并发容器的使用,如ArrayList、LinkedList、HashSet、HashMap等基础容器在并发环境下可能存在问题,Java提供了一些线程安全的容器,如Vector、HashTable以及java.util.concurrent包下的...