《Java Concurrency In Practice》读书笔记

《Java Concurrency In Practice》读书笔记一-Introduction2009-11-08 10:37 P.M. 一直感觉自己并发编程方面基础很弱,虽然于concurrent包有所了解,但一直是零乱而不系统,终于买到《Java Concurrency In Practice》英文版(中文版翻译的太烂),开始系统的学习并发编程。以后会把笔记都放在这里,希望坚持下去。
Chapter1--Introduction,主要是对并发的历史回顾及其利弊分析,权且当作是线程基础知识的扫盲。

Threads allow multiple streams of program control flow to coexist within a process. They share process-wide resources such as memory and file handles, but each thread has its own program counter, stack, and local variables. Threads also provide a natural decomposition for exploiting hardware parallelism on multiprocessor systems; multiple threads within the same program can be scheduled simultaneously on multiple CPUs.线程之间可以共享内存和文件句柄等资源,而且每个线程拥有自己的计数器,栈和局部变量。

Benefits of Threads:
1. Exploiting Multiple Processors,这个也是最大的好处。
2.Simplicity of Modeling, A complicated, asynchronous workflow can be decomposed into a number of simpler, synchronous workflows each running in a separate thread, interacting only with each other at specific synchronization points.通过建模来将复杂的异步工作流分解成多个简单的同步流。并且每个线程执行一个同步流,多个线程协作完成。RMI和Servlect就是这样的框架,The framework handles the details of request management, thread creation, and load balancing, dispatching portions of the request handling to the appropriate application component at the appropriate point in the work-flow。
3.Simplified Handling of Asynchronous Events
4.More Responsive User Interfaces,这两点主要是thread-per-client模式。

Risks of Threads:
1.Safety Hazards,安全问题也是最大问题。
2.Liveness Hazards,线程调度问题,deadlock,starvation ,livelock 问题。
3.Performance Hazards,线程调度和同步引起的性能问题。
Frameworks introduce concurrency into applications by calling application components from framework threads. Components invariably access application state, thus requiring that all code paths accessing that state be thread-safe.


Chapter2--Thread Safety,线程安全的解释及其相应手段:原子,锁等。
1. Whenever more than one thread accesses a given state variable, and one of them might write to it, they all must coordinate their access to it using synchronization. The primary mechanism for synchronization in Java is the synchronized keyword, which provides exclusive locking, but the term "synchronization" also includes the use of volatile variables, explicit locks, and atomic variables.

2. 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.
3. When designing thread-safe classes, good object-oriented techniques encapsulation, immutability, and clear specification of invariants are your best friends.


4. Thread Safe的定义: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.

5. Thread-safe classes encapsulate any needed synchronization so that clients need not provide their own.譬如Vector类,调用者无须再去同步。

6. Stateless objects are always thread-safe.stateless object即完全没有自己的变量等的对象,它执行的变量都是调用者传入的。譬如这个Servlect:

@ThreadSafepublic class StatelessFactorizer implements Servlet { public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); BigInteger[] factors = factor(i); encodeIntoResponse(resp, factors); } }
7. Race Condition的类型:check-then-act: you observe something to be true (file X doesn't exist) and then take action based on that observation (create X); but in fact the observation could have become invalid between the time you observed it and the time you acted on it (someone else created X in the meantime), causing a problem (unexpected exception, overwritten data, file corruption).


8. Operations A and B are atomic with respect to each other if, from the perspective of a thread executing A, when another thread executes B, either all of B has executed or none of it has. An atomic operation is one that is atomic with respect to all operations, including itself, that operate on the same state.
9. Compound Action:To ensure thread safety, check-then-act operations (like lazy initialization) and read-modify-write operations (like increment) must always be atomic. We refer collectively to check-then-act and read-modify-write sequences as compound actions: sequences of operations that must be executed atomically in order to remain thread-safe
concurrent包下的atomic包针对各个基础类型的变量进行原子封装,但不支持浮点运算。

10. Where practical, use existing thread-safe objects, like AtomicLong, to manage your class's state. It is simpler to reason about the possible states and state transitions for existing thread-safe objects than it is for arbitrary state variables, and this makes it easier to maintain and verify thread safety.


11. To preserve state consistency, update related state variables in a single atomic operation.原子操作只能针对单个变量,如果涉及到多个原子变量,没有同步同样非线程安全:


@NotThreadSafepublic class UnsafeCachingFactorizer implements Servlet { private final AtomicReference<BigInteger> lastNumber = new AtomicReference<BigInteger>(); private final AtomicReference<BigInteger[]> lastFactors = new AtomicReference<BigInteger[]>(); public void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber.get())) encodeIntoResponse(resp, lastFactors.get() ); else { BigInteger[] factors = factor(i); lastNumber.set(i); lastFactors.set(factors); encodeIntoResponse(resp, factors); } }}这个时候只需要synchronized该方法即可:@ThreadSafepublic class SynchronizedFactorizer implements Servlet { @GuardedBy("this") private BigInteger lastNumber; @GuardedBy("this") private BigInteger[] lastFactors; public synchronized void service(ServletRequest req, ServletResponse resp) { BigInteger i = extractFromRequest(req); if (i.equals(lastNumber)) encodeIntoResponse(resp, lastFactors); else { BigInteger[] factors = factor(i); lastNumber = i; lastFactors = factors; encodeIntoResponse(resp, factors); } }}A synchronized method is a shorthand for a synchronized block that spans an entire method body, and whose lock is the object on which the method is being invoked. (Static synchronized methods use the Class object for the lock.) synchronized采用的是intrinsic lock,也是reentrant lock,允许当获取一个锁后,开始执行,中间某个动作能够继续获取锁。考虑下面的情况:public class Widget { public synchronized void doSomething() { ... }}public class LoggingWidget extends Widget { public synchronized void doSomething() { System.out.println(toString() + ": calling doSomething"); super.doSomething(); }}如果不允许重入锁,则会导致LoggingWidget的doSomething永远无法执行。 11. For each mutable state variable that may be accessed by more than one thread,all accesses to that variable must be performed with the same lock held. In this case, we say that the variable is guarded by that lock. Every shared, mutable variable should be guarded by exactly one lock. Make it clear to maintainers which lock that is. For every invariant that involves more than one variable, all the variables involved in that invariant must be guarded by the same lock. 12. There is no inherent relationship between an object's intrinsic lock and its state; an object's fields need not be guarded by its intrinsic lock, though this is a perfectly valid locking convention that is used by many classes.Acquiring the lock associated with an object does not prevent other threads from accessing that objectthe only thing that acquiring a lock prevents any other thread from doing is acquiring that same lock. The fact that every object has a built-in lock is just a convenience so that you needn't explicitly create lock objects.每个对象都有一个锁,但对象的状态与锁无关。即使有多个线程等待某对象的锁,但同样可以有多个线程来操作这个对象。 13. synchronize方法需要考虑性能瓶颈,上面的方法因为synchronized范围太大会导致一个时间只能有一个请求,这会严重降低并发度,重构如下:@ThreadSafepublic 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); }} 14. There is frequently a tension between simplicity and performance. When implementing a synchronization policy, resist the temptation to prematurely sacriflce simplicity (potentially compromising safety) for the sake of performance. Avoid holding locks during lengthy computations or operations at risk of not completing quickly such as network or console I/O.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值