Java并发编程实战
来源:互联网 发布:java支持数据库的套件 编辑:程序博客网 时间:2024/05/01 12:41
进程与线程
操作系统可以使计算机同时能运行多个程序,每个不同的程序在单独的进程中运行。
同一个进程可以有多个线程的程序控制流。线程可以共享进程范围内的资源,但每个线程有各自的计数器,栈和局部变量。
多线程可以提升资源的利用率及系统吞吐量。尤其是多处理器的环境,可以提高处理器资源的利用率。
线程的6种状态:
- New(新创建)
- Runnable(可运行)
- Blocked(阻塞)
- Waiting(等待)
- Timed Waiting(计时等待)
- Terminated( 终止)
多线程带来并发问题:
- 安全性问题 (共享对象的可变状态的正确性和一致性)
- 活跃性问题 (死锁,饥饿,活锁,丢失信号)
- 性能问题 (多个线程的上下文切换,线程创建与调度)
所有并发问题都是源于多线程访问共享对象的可变状态。
线程安全性:
核心是对对象状态访问操作的管理,特别是对共享的和可变的状态的访问。
什么是线程安全的类?
当多个线程访问某个类的对象时,主调代码不要额外的同步或协调,这个对象都表现出正确的行为,这个类是线程安全的。
哪些类是线程安全的类?
- 无状态
- 状态不可修改(所有的域是final, 只通过构造器初始化,对象域不逸出)
- 在访问可变状态变量时使用同步(原子操作)
Java的同步机制,包括内置锁synchronized, volatile变量,原子变量,显式锁。
线程安全性核心是正确性
正确性:包括 各种不变性条件(Invariant)来约束对象状态,以及后验条件(Postcondition)来描述对象操作结果。
//不变性条件是 end date 在 start date 之后public class Range { private Date start; private Date end; public Range(Date start, Date end) { this.start = start; this.end = end; }}
在并发编程中,当某个计算的正确性取决于多个线程的执行时序是,称为竞争条件(Race Condition)。常见的竞争条件类型是“先检查后执行”。
示例1:延时初始化的race condition
public class CustomerService { private Map<String, Customer> customers = new HashMap<>(); public Customer getCustomer(String name) { if(customers.get(name) == null) {//race condition customers.put(name, new Customer(name)); } return customers.get(name); }}
示例2:复合操作的race condition
计数器i++, 包括“读取-修改-写入”
public class Counting { private int i; public void increase() { i++; //race condition } public int getCount() { return i; }}
要保持状态的一致性,需要在单个原子操作中更新所有相关状态变量。
上面的示例可以使用加锁和原子类型变量来实现原子操作:
public class CustomerService { private Map<String, Customer> customers = new HashMap<>(); public synchronized Customer getCustomer(String name) { //加内置锁 if(customers.get(name) == null) {//race condition customers.put(name, new Customer(name)); } return customers.get(name); }}
public class Counter { private final AtomicLong count = new AtomicLong();//原子类型类 public void increase() { count.incrementAndGet(); } public long getCount() { return count.get(); }}
加锁机制
Java的内置锁机制保证操作的原子性。
对可能被多个线程同时访问的可变状态变量,需要加锁保护。
对每个包含多个变量的不变性条件,涉及的所有变量都需要加同一个锁保护。
静态synchronized方法的锁是Class对象锁,和非静态synchronized方法的不是同一个锁。
如果使用synchronized同步,可能影响活跃性和性能,所有要减小同步代码块的颗粒度。
- Java并发编程实战
- Java并发编程实战--
- Java并发编程实战-
- Java 并发编程实战
- java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Java并发编程实战
- Mysql学习笔记二——基础查询where练习
- 设计模式学习之备忘录模式
- 初识线程
- 如何提交代码到GitHub
- 正则速记理解技巧
- Java并发编程实战
- (8.1.5.9)Android Testing Support Library翻译之 ATSL 中的 JUnit4 规则
- Trie
- IOS 3DTouch
- (8.1.5.10)Android Testing Support Library翻译之 UI Automator
- 湖北民族学院oj 1777(DFS) 之 查找细胞
- (8.1.5.11)Android Testing Support Library翻译之 可访问性检查
- 浅谈web前端的简单优化
- js实现图片预览