--注:由于Java Concurrency in Practice时间久远业已脱销,所以本人对读到的一些要点进行整理,主要用来个人进一步深化学习,书中原文会加中英文注释,自己的白话仅有中文。
Chapter 2. Thread Safety线程安全
If multiple threads access the same mutable state variable without appropriate synchronization, your program is broken. There are three ways to fix it:
如果多个线程在没有适当的同步机制情况下访问同一个状态易变的变量, 那么你的程序容易被打破。下面有三种解决方式:
Don't share the state variable across threads;
不要在多个线程间共享状态变量;
Make the state variable immutable; or
保持状态变量不可变;
Use synchronization whenever accessing the state variable.
当并发访问状态变量时候注意使用同步机制(同步代码块或锁);
2.1. What is Thread Safety? 什么是线程安全
A class is thread-safe if it behaves correctly when accessed from multiple threads, regardless of the scheduling or interleaving of the execution of those threads by the runtime environment, and with no additional synchronization or other coordination on the part of the calling code.
一个类如果被多个线程访问且运行正常那么他是安全的,无论被运行环境如何安排或交错那些线程执行,并且没有在被调用代码块添加任何其他同步机制或其他协调方式。
2.1.1. Example: A Stateless Servlet
@ThreadSafe
public class StatelessFactorizer implements Servlet {
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
encodeIntoResponse(resp, factors);
}
}
以上例子符合保持线程安全的三种方式。
2.2. Atomicity原子性
Listing 2.2. Servlet that Counts Requests without the Necessary Synchronization. Don't Do this.
@NotThreadSafe
public class UnsafeCountingFactorizer implements Servlet {
private long count = 0;
public long getCount() { return count; }
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
++count;//非原子操作
encodeIntoResponse(resp, factors);
}
}
以上程序是对count进行计算,需要对其进行read+modify+write的操作,在多个线程并发访问程序的时候,如果某个线程在read+modify+write三步操作的任何一步阻塞,则可能会造成数据的不同步,进而影响数据真实性。那么,这里管read+modify+write三步操作为不可拆分的操作,只有read+modify+write三步操作同时成功执行,才能保证数据真实性,那么三个操作构成了
原子操作。
2.2.1. Race Conditions竞争状况
有竞争才会涉及并发访问。
2.2.2. Example: Race Conditions in Lazy Initialization
Listing 2.3. Race Condition in Lazy Initialization. Don't Do this.
@NotThreadSafe
public class LazyInitRace {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance() {
if (instance == null)//多个线程访问时候,如果某个线程阻塞,那么这个线程重新抢占时间后它读到的数据可能就是脏数据了
instance = new ExpensiveObject();
return instance;
}
}
2.2.3. Compound Actions复合行为(操作)
上面说了read+modify+write为一个不可拆分的原子操作,而其实质上还是三个操作,将这三个操作在程序级加上同步机制使其构成一个原子操作,我们指出这三个操作就是一个复合操作。那么在java的api也提供了一些原子操作工具类,来替代显示的synchronize这些标识。
@ThreadSafe
public class CountingFactorizer implements Servlet {
private final AtomicLong count = new AtomicLong(0);//可以用原子方式更新的 long 值。
public long getCount() { return count.get(); }
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
count.incrementAndGet();
encodeIntoResponse(resp, factors);
}
}
上面图片中列出了软件包 java.util.concurrent.atomic(类的小工具包,支持在单个变量上解除锁定的线程安全编程。 ) 中的支持同步更新的线程安全类。
2.3. Locking 锁
2.3.1. Intrinsic Locks 内在锁
synchronized (lock) {
// Access or modify shared state guarded by lock
}
2.3.2. Reentrancy 重入
当一个锁被某个线程持有,那么其他线程不可再获取这把锁,但是持有这把锁的线程可以重新持有。其实在运行时环境中有一个对同步锁计数的机制,即锁空闲态时候,count=0,当某个线程持有这把锁后count++,并记录这把锁的owner,当持有这把锁的线程再次持有这把锁后继续count++。
Listing 2.7. Code that would Deadlock if Intrinsic Locks were Not Reentrant.
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling doSomething");
//比如程序运行时,某个线程执行到这里阻塞的话,没有重新进入super.doSomething(),那么即造成死锁。
super.doSomething();
}
}
2.4. Guarding State with Locks 用锁保持状态
如何正确使用锁机制,要根据实际情况有一个合适的力度,不能随随便的就把某个方法直接synchronized(可能将不需要同步的部分也加锁,那么对性能造成了一定的影响),也不能将read-modify-write的某一个或者两个操作放入原子操作(没有正确分析原子操作构成)。
2.5. Liveness and Performance 活性与性能
Listing 2.8. Servlet that Caches its Last Request and Result.
@ThreadSafe
public class CachedFactorizer implements Servlet {
@GuardedBy("this") private BigInteger lastNumber;
@GuardedBy("this") private BigInteger[] lastFactors;
@GuardedBy("this") private long hits;
@GuardedBy("this") private long cacheHits;
public synchronized long getHits() { return hits; }
public synchronized double getCacheHitRatio() {
return (double) cacheHits / (double) hits;
}
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = null;
synchronized (this) {
++hits;
if (i.equals(lastNumber)) {
++cacheHits;
factors = lastFactors.clone();
}
}
if (factors == null) {
factors = factor(i);
synchronized (this) {
lastNumber = i;
lastFactors = factors.clone();
}
}
encodeIntoResponse(resp, factors);
}
}
以上例子,正式遵循保证原子操作,又不滥用原子操作,保证程序的数据可靠与性能良好。
- 大小: 27.8 KB
分享到:
相关推荐
<<java并行编程>>英文版chm格式,英文名称<Java Concurrency in Practice>,一直想买这本书,但总是缺货,找到了电子版,分享给大家。 Java Concurrency in Practice By Brian Goetz, Tim Peierls, Joshua Bloch,...
Java Concurrency in Practice 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者...
《Java并发编程实践》是Java开发者必读的经典之作,由Brian Goetz等多位专家共同撰写。这本书深入浅出地探讨了Java平台上的并发问题,帮助读者理解和掌握如何编写高效、可靠且可维护的多线程应用程序。以下是该书...
Basic concepts of concurrency and thread safety Techniques for building and composing thread-safe classes Using the concurrency building blocks in java.util.concurrent Performance optimization dos ...
Java Concurrency in practice
《Java Concurrency in Practice》是Java并发编程领域的一本经典著作,由Brian Goetz、Tim Peierls、Joshua Bloch、Joseph Bowles和Doug Lea等专家共同编写。这本书深入探讨了Java平台上的多线程和并发编程,旨在...
java_concurrency_in_practice.pdf jcip-examples-src.jar jcip-annotations-src.jar 英文版是高清晰的,实战和实践都是同一帮人对英文版书的翻译,网传实战的翻译质量更好,实战是2012年出版的,应该是对前一版实践...
Java Concurrency in Practice JAVA并发编程实践中文版(全)第二部分
《Java Concurrency In Practice》是一本关于Java并发编程的经典著作,由Brian Göetz、Tim Peierls、Joshua Bloch、Joseph Bowbeer、David Holmes和Doug Lea共同编写。本书深入探讨了Java平台上的多线程编程技巧,...
java concurrency in practice 经典的多线程编程书籍,英文版
Chapter 2. A Tour of C++: The Basics Chapter 3. A Tour of C++: Abstraction Mechanisms Chapter 4. A Tour of C++: Containers and Algorithms Chapter 5. A Tour of C++: Concurrency and Utilities Part II: ...
本笔记将深入探讨《Java Concurrency In Practice》这本书中的核心概念,结合Guava库的实际使用案例,帮助读者理解并掌握Java并发编程的精髓。 首先,我们来了解Java并发的基础知识。Java提供了丰富的并发工具类,...
首先,"Java Concurrency in Practice"是Java并发编程的经典之作,由Brian Goetz、Tim Peierls、Joshua Bloch、David Holmes和Doug Lea合著。这本书提供了一套实用的指导原则、设计模式和最佳实践,帮助Java开发者...
- **书名**:《Java并发实践》(Java Concurrency in Practice) - **作者**:Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, Doug Lea - **出版社**:Addison Wesley Professional - **...
博文链接:https://projector.iteye.com/blog/209730