读《JAVA并发实践》笔记---第一章(介绍),第二章(线程安全)
2017-05-27 18:20
260 查看
线程的优点:
1.可以使用多处理器。一个单线程应用只能运行中一个处理器上,如果不运用多线程那么在双处理器系统中相当于放弃了百分之五十的CPU资源。
2.模型的简化。就如同工厂生产线上工人的分工,把一个工人当成一个线程,只需要处理同样类型的任务。不需要考虑在各任务之间来回切换。这些优点通常被一些框架所用,比如Servlets或者远程方法调用。servlet开发者不需要当心容器究竟同时正在处理多个请求。这样可以简化组件开发。
3.对异步事件的简单处理。这就关系到程序的阻塞和非阻塞的问题。给每一个请求一个线程,可以让请求之间不再相互影响。
4.用户界面的更佳响应性。
线程的缺点:
1.安全危险。多线程中各个操作的顺序是不可预测的。可能会导致脏读等数据问题
2.活跃度危险。例如死锁,饥饿,活锁。
3.性能危险。多线程的上下文切换,CPU的时间会花费在线程的调度而不是运行上。当线程共享数据的时候,必须使用同步机制,这个机制会限制编译器的优化。
什么是线程安全:
当多线程在访问一个类时,不用考虑在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必作其他的协调,这个类的行为依然是正确的,那么称这个类是线程安全的。
原子性:
从“读写改”三步操作去理解原子性,例如多线程对同一个资源进行自增或者自减可能导致数据不准确。
竞争条件:
最常见的一种竞争条件是:检查再运行(check-then-act)
假设有操作A和B,如果从执行A的线程的角度看,当其他线程执行B时,要么B全部执行完成,要么一点都没有执行,这样A和B互为原子操作。一个原子操作是指:该操作对于所有操作,包括它自己,都满足前面描述的状态。
java.util.concurrent.atomic包中包含了原子变量类,这些类用来实现数组和对象引用的原子状态转换。
锁:
内部锁:
每个Java对象都可以隐式的扮演一个同步的锁的角色;这些内置的锁被称为内部锁或监视器锁。执行线程进入synchronized块之前会自动获得锁;而无论通过正常控制退出还是从块中抛出异常,线程都会自动释放锁。获得内部锁的唯一途径是:进入这个内部锁保护的同步快或方法。
内部锁在Java中扮演“互斥锁”的角色,意味着至多只有一个线程可以拥有锁。当A线程请求B线程所占有的一个锁的时候,线程A必须等待或者阻塞,直到B释放锁。如果B不释放锁,那么A将永远等下去。
锁的重进入:
内部锁是可重进入的。当一个线程请求该线程已经占有的锁时,请求会成功。
重进入的实现是通过为每个锁关联一个请求计数和占有它的线程。当请求计数为0时,表示它未被占有。线程请求一个未被占有的锁,jvm将记录占有者,并将请求计数更新为1。如果同一线程再次请求这个锁,请求计数递增;当线程退出同步快,计数递减。当请求计数为0时,锁被释放。
方便了锁的封装,避免死锁。
1.可以使用多处理器。一个单线程应用只能运行中一个处理器上,如果不运用多线程那么在双处理器系统中相当于放弃了百分之五十的CPU资源。
2.模型的简化。就如同工厂生产线上工人的分工,把一个工人当成一个线程,只需要处理同样类型的任务。不需要考虑在各任务之间来回切换。这些优点通常被一些框架所用,比如Servlets或者远程方法调用。servlet开发者不需要当心容器究竟同时正在处理多个请求。这样可以简化组件开发。
3.对异步事件的简单处理。这就关系到程序的阻塞和非阻塞的问题。给每一个请求一个线程,可以让请求之间不再相互影响。
4.用户界面的更佳响应性。
线程的缺点:
1.安全危险。多线程中各个操作的顺序是不可预测的。可能会导致脏读等数据问题
2.活跃度危险。例如死锁,饥饿,活锁。
3.性能危险。多线程的上下文切换,CPU的时间会花费在线程的调度而不是运行上。当线程共享数据的时候,必须使用同步机制,这个机制会限制编译器的优化。
什么是线程安全:
当多线程在访问一个类时,不用考虑在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必作其他的协调,这个类的行为依然是正确的,那么称这个类是线程安全的。
原子性:
从“读写改”三步操作去理解原子性,例如多线程对同一个资源进行自增或者自减可能导致数据不准确。
竞争条件:
最常见的一种竞争条件是:检查再运行(check-then-act)
假设有操作A和B,如果从执行A的线程的角度看,当其他线程执行B时,要么B全部执行完成,要么一点都没有执行,这样A和B互为原子操作。一个原子操作是指:该操作对于所有操作,包括它自己,都满足前面描述的状态。
java.util.concurrent.atomic包中包含了原子变量类,这些类用来实现数组和对象引用的原子状态转换。
锁:
内部锁:
每个Java对象都可以隐式的扮演一个同步的锁的角色;这些内置的锁被称为内部锁或监视器锁。执行线程进入synchronized块之前会自动获得锁;而无论通过正常控制退出还是从块中抛出异常,线程都会自动释放锁。获得内部锁的唯一途径是:进入这个内部锁保护的同步快或方法。
内部锁在Java中扮演“互斥锁”的角色,意味着至多只有一个线程可以拥有锁。当A线程请求B线程所占有的一个锁的时候,线程A必须等待或者阻塞,直到B释放锁。如果B不释放锁,那么A将永远等下去。
锁的重进入:
内部锁是可重进入的。当一个线程请求该线程已经占有的锁时,请求会成功。
重进入的实现是通过为每个锁关联一个请求计数和占有它的线程。当请求计数为0时,表示它未被占有。线程请求一个未被占有的锁,jvm将记录占有者,并将请求计数更新为1。如果同一线程再次请求这个锁,请求计数递增;当线程退出同步快,计数递减。当请求计数为0时,锁被释放。
方便了锁的封装,避免死锁。
相关文章推荐
- Java 螺纹第三版 第一章Thread介绍、 第二章Thread创建和管理学习笔记
- 数据结构与算法分析笔记-介绍&第一章
- C++ primer 复习笔记 (第一章、第二章)
- 【学习笔记】Thinking in java (第三版)第一章 对象的介绍(Introduction to objects)
- SPRING IN ACTION 第4版笔记-第一章-002-DI介绍
- 【C】【笔记】《C和指针》 第一章 快速上手 第二章 基本概念 第三章 数据 第四章 语句 第五章 操作符和表达式
- core jave2:第一章java介绍;第二章java编辑环境
- 《Linux内核设计与实现》课本第一章第二章学习笔记
- Solr in action学习笔记 第一章 介绍
- 《Hadoop权威指南》笔记 第一章&第二章 MapReduce初探
- Linux第一章第二章学习笔记
- 【吼吼睡cocos2d学习笔记】第一章 - 介绍cocos2d
- 数据库与MySQL 【数据库高效编程 - 学习笔记 第一章、第二章】
- QT creator 工具的介绍 qt学习笔记第二章
- 第一章 介绍 第二章 安装python 第三章 最初的步骤
- 培训教材笔记-介绍&第一章
- 深入浅出MFC学习笔记:(第一章:win32基本概念,第二章:C++的重要性质)
- Linux内核设计与实现笔记之第一章、第二章
- 第一行代码学习笔记-第一章 开始启程-3.安卓Log方法介绍
- 《Linux内核设计与实现》课本第一章&第二章学习笔记