We want to ensure that the synchronization happens at the right level for each class so we don’t compromise thread safety but still enjoy good concurrency.
//同步一个对象or相应的互斥的方法 Synchronizing instances is fairly common but has some problems. For one,its scope is the entire object, and that becomes the level of granularity for concurrency. This limits us to at most one synchronized operation on the entire object at any time. If all the operations on the object are mutually exclusive, such as add and remove on a collection, then this is not entirely bad, though it can certainly be better. However, if the object can support multiple operations, such as drive() and sing(), that can run concurrently but need to be synchronized with other operations, such as drive() and tweet(), which should be mutually exclusive, then synchronizing on the instance will not help with speed. In this case, we should have multiple synchronization points within the objects for these methods.
public long getUnitsAvailable() { return level.get(); }We got rid of the synchronized marking from getUnitsAvailable(), since the AtomicLong takes care of thread safety and visibility for access to the value it holds.
public boolean useEnergy(final long units) { final long currentLevel = level.get(); if (units > 0 && currentLevel >= units) { return level.compareAndSet(currentLevel, currentLevel - units); } return false; }CAS:We have much better speed for reads and safety for writes as well.
private void replenish() { if (level.get() < MAXLEVEL) level.incrementAndGet(); }The replenish() is also not asking for an exclusive lock. It grabs the level in a thread-safe manner and then, without holding any lock, increments the value. This is OK since there is only one thread increasing the energy level. If the method found the value to be lower than MAXLEVEL, it remains lower, even though the value may decrease. The increment itself is thread safe, and there is no issue of consistency.
public synchronized void stopEnergySource() { replenishTask.cancel(false); }//调用频率低 使用实例对象级别锁We have left the stopEnergySource() method marked synchronized because the call to this method will be so infrequent there is no need to make this locking any more granular(粒度) at this point.
//尽力引入对象锁 Check to see whether there are places where you can introduce lock objects instead of synchronizing on the entire instance.
