- 浏览: 526111 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (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. 线程 的风险
1.1 安全风险
线程不安全:
Public class UnsafeSequence{
Private int value;
Public int getNext(){
Return value++;
}
}
线程安全:
Public class UnsafeSequence{
Private int value;
Public synchronized int getNext(){
Return value++;
}
}
1.2 活跃度 (liveness) 风险
当一个活动进入某种永远它无法再继续执行的状态时, liveness failure 就发生了。例如死锁 (deadlock) 、饥饿 (starvation) 和活锁 (livelock) 。
1.3 性能风险
性能问题涉及很多方面,包括服务时间、响应性、吞吐量、资源消费或者可伸缩性的不良表现。设计良好的应用程序中使用线程,能够获得纯粹的性能收益,但是线程仍然会给运行带来一定的开销:
上下文切换: 当调度程序临时挂起当前运行的线程时,另一个线程开始运行,这再多个线程组成的应用程序中是很频繁的,并且带来巨大的系统开销:
l 保存和恢复线程执行的上下文,离开执行现场,并且 CPU 时间会花费在对线程的调度而不是在运行上。
l 当线程共享数据的时候,他们必须使用同步机制,这个机制会限制编译器的优化
l 同步也能够清空或者锁定内存和高速缓存,并在共享内存的总线上创建同步通信
1.4 线程无处不在
线程实际上是无处不在的,即使你的程序没有使用多线程,然而你依赖的第三方或者你的程序所处的框架会为你创建线程。在你使用第三方包的时候,尤其要注意线程安全问题。
2. 线程安全
2.1 概览
编写线程安全的代码,本质上就是管理对状态的访问,而且通常都是共享的、可变的状态。 无论何时,只要有多于一个的线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用协调线程对变量的访问。
并发编程是保证正确性的前提下对性能的追求。
在没有正确使用同步的情况下,如果多个线程访问了同一个变量。你的程序就存在隐患。有 3 个方法可以修复它:
l 不要跨线程共享变量
l 使变量为不可变的
l 在任何访问状态变量的时候都使用同步
设计线程安全的类时,优秀的面向对象技术 --- 封装、不可变性以及明确的不变约束 — 会给你提供诸多的帮助。
2.2 什么是线程安全
非线程安全的实例:
Public class ImageServlet implements Servlet{
Public String imageURL;
Public void service(ServletRequest req, ServletResponse resp) {
imageURL = req.getParameter(“imageURL”);
…
out.println(imageURL);
}
}
分析: 由上面图可以看出, ThreadA ,写入新值后,在还没有写入 Client 之前, Thread B 又写入了新值,从而客户 A 上传图片,显示在页面上时,变成了客户 B 上传的图片。
改进:
Public class ImageServlet implements Servlet{
Public void service(ServletRequest req, ServletResponse resp) {
String imageURL = req.getParameter(“imageURL”);
…
out.println(imageURL);
}
}
这样改进以后,就线程安全了,记住:
无状态的 Servlet (对象)永远是线程安全的。
2.3 原子性
由于不是原子性操作而造成的线程安全问题:
Public class UnsafeCount implements Servlet{
Public int count;
Public void service(ServletRequest req, ServletResponse resp) {
count++;
…
out.println(imageURL);
}
}
2.3.1 竞争条件 – check-then-act
线程安全问题的形成,通常有一定的竞争条件。检查再运行是典型的竞争条件:
Public class LazyInitRace {
Private ExpensiveObject instance = null;
Public ExpensiveObject getInstance(){
If (instance == null)
Instance = new ExpensiveObject();
Return instance;
}
}
2.3.2 复合操作
刚才计数器的问题和 check-then-act 的问题的根本原因是这些操作并不是一步操作,专业术语称为原子操作:
假设有操作 A 和 B ,如果从执行 A 的线程的角度看,当其他线程执行 B 时,要么 B 全部全部执行完成,要么一点都没有执行,这样 A 和 B 互为原子操作。
对于上面说的计数器,我们可以如下改进:
Public class CountFactorizer implements Servlet{
Public final AtomicLong count = new AtomicLong(0);
Public void service(ServletRequest req, ServletResponse resp) {
Count.incrementAndGet();
…
out.println(imageURL);
}
}
2.4 锁
2.4.1 内部锁
Java 提供了原子性的内置锁机制: sychronized 块。它包含两个部分:锁对象的引用和这个锁保护的代码块:
synchronized(lock) {
// 访问或修改被锁保护的共享状态
}
内部锁扮演了互斥锁( mutual exclusion lock, 也称作 mutex )的角色,一个线程拥有锁的时候,别的线程阻塞等待。
2.4.2 重进入(Reentrancy )
重入性:指的是同一个线程多次试图获取它所占有的锁,请求会成功。当释放锁的时候,直到重入次数清零,锁才释放完毕。
Public class Widget {
Public synchronized void doSomething(){
…
}
}
Public class LoggingWidget extends Widget {
Public synchronized void doSomething(){
System.out.println(toString()+”:calling doSomething”);
Super.doSomething();
}
}
2.6 活跃度和性能
弱并发性:
Public class CountFactorizer implements Servlet{
Public int count = 0;
Public synchronized void service(ServletRequest req, ServletResponse resp) {
Count++;
…
}
}
改进:
Public class CountFactorizer implements Servlet{
Public int count = 0;
Public void service(ServletRequest req, ServletResponse resp) {
Synchronized(this){
Count++;
}
…
}
}
并不是同步块越小越好,决定 synchronized 块大小的需要权衡各种设计要求,包括安全性、简单性和性能。有些耗时的计算或者操作,比如网络或控制台 I/O ,难以快速完成,执行这些操作期间不要占有锁。
发表评论
-
死锁实例
2011-05-19 14:21 1946下面这道题,是考死锁的,比较简单,想两个问题: 1.什么时候 ... -
Java存储模型
2011-05-18 13:29 01.什么是存储模型 没有适当的同步,编译器生成指令的次序,可 ... -
设计模式-组合模式
2011-05-16 15:48 1101组合模式的定义: 将对象组合成树的形式来表示整体和局部之 ... -
CompleteService介绍和使用实例
2011-05-11 17:31 3985当向Executor提交批处理任务时,并且希望在它们完成后获得 ... -
CyclicBarrier的使用实例
2011-05-11 15:45 1481CyclicBarrier允许给定数量的线程全部到达关卡点时, ... -
CopyOnWriteArrayList工作原理和实例
2011-05-05 23:43 3384CopyOnWriteArrayList顾名思义,在写入操作时 ... -
Semaphore的介绍和使用实例
2011-04-27 22:32 2809Semaphore可以用来控制能 ... -
FutureTask的使用方法和使用实例
2011-04-27 15:34 13313FutureTask是一种可以取消的异步的计算任务。它的计算是 ... -
CountDownLatch的使用实例
2011-04-26 22:20 8214CountDownLatch CountDownl ... -
Java 并发编程基础-共享对象
2011-04-19 14:48 1447Java 并发编程基础 ... -
从JVM并发看CPU内存指令重排序(Memory Reordering)
2011-04-18 16:17 1481我们都知道,现在的计算机, cpu 在计算的时候 ... -
Java多线程基础
2011-04-13 15:52 4739Java 多线程基础 ... 2 ... -
硬件同步原语(CAS)理论
2010-09-24 22:13 6990在Java并发编程中,常常 ... -
java5中使用interrupt()来停止java线程的方法(转)
2010-08-18 23:24 3113在开发java多线程时,如果要停止线程这个问题很头痛吧,不过在 ... -
Java 中的Double Check Lock(转)
2010-07-27 21:13 8095对于多线程编程来说,同步问题是我们需要考虑的最多的问题,同步的 ... -
并发访问的问题解决方案
2010-07-26 18:15 1999目前正在做基于Red 5 的Meeting系统,我们会在Mee ... -
用并发包中的重入锁实现生产消费模型
2010-06-15 00:07 1434传统的生产消费模型,实际上是通过一个条件来调节生产者和消费者线 ... -
ThreadLocal原理(转)
2010-03-24 18:06 2164http://jzhua.iteye.com/blog/517 ... -
(转)Java偏向锁实现原理(Biased Locking)
2010-03-21 22:24 1364http://www.iteye.com/topic/5180 ... -
生产消费模型实例
2010-03-02 23:23 1711“生产者-消费者-仓储”模型,包含三种角色: 1.生产者 ...
相关推荐
在本资源中,我们有两个主要的学习材料:一个关于“Java并发编程基础”的PPT和一个包含DEMO示例,另一个是“操作系统概述”的PPT。这些资料对于理解Java多线程编程以及操作系统的基础原理至关重要。 首先,让我们...
### Java并发编程基础 - **并发与并行**:并发是指多个任务在同一时间段内被执行(但不一定同一时刻),而并行则是指多个任务同时执行。理解这两者的区别对于深入学习并发编程至关重要。 - **Java并发机制**:Java...
JAVA并发编程艺术 高清pdf : 1.并发变成的挑战 2. java并发机制的底层实现原理 3. java 内存模型 4. java并发编程基础 5.java中的锁。。。。。。。
《Java并发编程的艺术》内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程基础、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深入的讲解,同时...
### 一、Java并发编程基础 #### 1.1 并发与并行的概念 - **并发**:指多个事件在同一时间段内发生。 - **并行**:指多个事件在同一时刻发生。 在Java并发编程中,通常会涉及多个线程共享资源并同时运行的情况,...
### 一、Java并发编程基础 #### 1.1 并发与并行 - **并发**:指在同一时间段内处理多个任务的能力。 - **并行**:指同一时刻处理多个任务的能力。并行依赖于多处理器或多核处理器的支持。 #### 1.2 Java并发工具类...
### Java并发编程基础 #### 1. 并发与并行 - **并发(Concurrency)**:指一个程序中存在多个执行序列(如线程)在逻辑上同时执行。 - **并行(Parallelism)**:指多个处理器同时执行不同的任务或指令,通常涉及硬件...
总之,《Java并发编程实战》是一本全面介绍Java并发编程的书籍,适合有一定Java基础并希望提升并发编程能力的开发者阅读。通过学习,你可以掌握解决并发问题的策略和技巧,编写出更加健壮和高效的多线程应用。
, 《Java并发编程的艺术》内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程基础、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深入的讲解,...
#### 一、Java并发编程基础 ##### 1.1 并发与并行概念区分 在Java并发编程实践中,首先需要理解“并发”与“并行”的区别。“并发”指的是多个任务同时进行,但实际上可能是在多线程环境下通过交替执行的方式实现的...
### Java并发编程基础 #### 1. 并发与并行 - **并发**:指的是多个任务在同一时间段内被执行(可能不是同一时刻)。 - **并行**:指的是多个任务在同一时刻被执行。 在Java中,并发主要是通过多线程来实现的,而...
本书不仅适合已经有一定Java编程经验的开发人员阅读,也适用于希望深入了解并发编程基础的新手。它从最基本的并发概念讲起,如进程与线程的区别、线程生命周期、线程调度策略等,并逐步深入到锁机制、死锁避免、原子...
此外,Java并发编程还包括对并发容器的使用,如ArrayList、LinkedList、HashSet、HashMap等基础容器在并发环境下可能存在问题,Java提供了一些线程安全的容器,如Vector、HashTable以及java.util.concurrent包下的...
《Java并发编程实战》提供了深入浅出的指导,涵盖了从基础理论到高级技术的广泛内容。 第一部分介绍了并发编程的基础,包括线程安全性的概念,如何构建线程安全的类,以及Java平台提供的并发工具如线程、同步机制等...
通过阅读《Java并发编程的艺术》这本书,开发者不仅可以掌握Java并发编程的基础知识,还能了解到一些高级特性和技巧,从而在实际开发中游刃有余。同时,附带的源码将有助于加深理解,提供实际操作的机会。
Java并发编程是软件开发中的一个关键领域,尤其是在大型企业级应用和分布式系统中。通过学习相关的书籍,开发者可以深入理解如何有效地设计和实现高效的多线程应用程序,避免并发问题,如竞态条件、死锁、活锁等。...
《JAVA并发编程实践》这本书是Java开发者深入理解并发编程的重要参考资料。它涵盖了Java并发的核心概念、工具和最佳实践,旨在帮助读者在多线程环境下编写高效、安全的代码。 并发编程是现代软件开发中的关键技能,...