【Notes】Effective Java 2nd -- Concurrency

Item 66: Synchronize access to shared mutable data

1. Not only does synchronization prevent a thread from observing an object in an inconsistent state, but it ensures thateach thread entering a synchronized method or block sees the effects of all previous modifications that were guarded by the same lock.

2. The language specification guarantees that reading or writing a variable is atomic unless the variable is of type long or double

3. While the language specification guarantees that a thread will not see an arbitrary value when reading a field,it does not guarantee that a value written by one thread will be visible to another. Synchronization is required for reliable communication between threads as well as for mutual exclusion.

4. Do not use Thread.stop. A recommended way to stop one thread from another is to have the first thread poll a boolean field that is initially false but can be set to true by the second thread to indicate that the first thread is to stop itself.

5. In fact, synchronization has no effect unless both read and write operations are synchronized

6. The actions of the synchronized methods in StopThread would be atomic even without synchronization. In other words, the synchronization on these methods is used solely for its communication effects, not for mutual exclusion

7. While the volatile modifier performs no mutual exclusion, it guarantees that any thread that reads the field will see the most recently written value

8. The best way to avoid the problems discussed in this item is not to share mutable data. Either share immutable data, or don’t share at all. In other words, confine mutable data to a single thread.

9. When multiple threads share mutable data, each thread that reads or writes the data must perform synchronization. Without synchronization, there is no guarantee that one thread’s changes will be visible to another

10. If you need only inter-thread communication, and notmutual exclusion, the volatile modifier is an acceptable form of synchronization


Item 67: Avoid excessive synchronization

1. In other words, inside a synchronized region, do not invoke a method that is designed to be overridden, or one provided by a client in the form of a function object

2. Locks in the Java programming language are reentrant, such calls won’t deadlock. The calling thread already holds the lock, so the thread will succeed when it tries to reacquire the lock.

3. As a rule, you should do as little work as possible inside synchronized regions. If you must perform some time-consuming activity, find a way to move the activity out of the synchronized region.

4. You should make a mutable class thread-safe (Item 70) if it is intended for concurrent use and you can achieve significantly higher concurrency by synchronizing internally than you could by locking the entire object externally. Otherwise, don’t synchronize internally. Let the client synchronize externally where it is appropriate.

5. StringBuffer instances are almost always used by a single thread, yet they perform internal synchronization. It is for this reason that StringBuffer was essentially replaced by StringBuilder, which is an unsynchronized StringBuffer


Item 68: Prefer executors and tasks to threads

1. In a cached thread pool, submitted tasks are not queued but immediately handed off to a thread for execution. If no threads are available, a new one is created.

2. Therefore, in a heavily loaded production server, you are much better off using Executors.newFixedThreadPool, which gives you a pool with a fixed number of threads.

3. In essence, the Executor Framework does for execution what the Collections Framework did for aggregation

4. The key abstraction is no longer Thread, which served as both the unit of work and the mechanism for executing it Now the unit of work and mechanism are separate. 

5. The key abstraction is the unit of work, which is called a task. There are two kinds of tasks: Runnable and its close cousin, Callable. The general mechanism for executing tasks is the executor service.


Item 69: Prefer concurrency utilities to wait and notify

1. The higher-level utilities in java.util.concurrent fall into three categories:executor framework, concurrent collections and synchronizers.

2. The concurrent collections provide high-performance concurrent implementations of standard collection interfaces such as List, Queue, and Map. To provide high concurrency, these implementations manage their own synchronization internally

3. Synchronizers are objects that enable threads to wait for one another, allowing them to coordinate their activities. The most commonly used synchronizers areCountDownLatchand Semaphore. Less commonly used are CyclicBarrier and Exchanger.

4. Unless you have a compelling reason to do otherwise,use ConcurrentHashMap in preference to Collections.synchronizedMap or Hashtable.

5. For interval timing, always use System.nanoTime in preference to System.currentTime- Millis. System.nanoTime is both more accurate and more precise, and it is not affected by adjustments to the system’s real-time clock.

6. You should always use the concurrency utilities in preference to wait and notify.

7. Always use the wait loop idiom to invoke the wait method; never invoke it outside of a loop.

8. The notifyAll method should generally be used in preference to notify.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值