Java Concurrency in Practice

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. 


Race condition:

Check-then-act:you observe something to be true (file X doesn't exist)Check-then-act,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). 


Using Atomic Long:

@ThreadSafe 
public class CountingFactorizer implements Servlet { 
private final AtomicLong count = new AtomicLong(0); 
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); 
} 
}

To preserve state consistency, update related state variables in a single atomic operation. 


Reentrancy

When a thread requests a lock that is already held by another thread, the requesting thread blocks. But because 
intrinsic locks are reentrant, if a thread tries to acquire a lock that it already holds, the request succeeds. Reentrancy 
means that locks are acquired on a per‐thread rather than per‐invocation basis. 


Volatile Variables

The compiler and runtime are put on notice that this variable is shared.Volatile variables are not cached in registers or in caches where they are hidden from other 
processors, so a read of a volatile variable always returns the most recent write by any thread.

You can use volatile variables only when all the following criteria are met: 
•  Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever 
updates the value; 
•  The variable does not participate in invariants with other state variables; and 
•  Locking is not required for any other reason while the variable is being accessed.

Locking can guarantee both visibility and atomicity; volatile variables can only guarantee visibility.


Immutable Holder for Caching a Number and its Factors. 
@Immutable 
class OneValueCache { 
private final BigInteger lastNumber; 
private final BigInteger[] lastFactors; 
public OneValueCache(BigInteger i, 
BigInteger[] factors) { 
lastNumber = i; 
lastFactors = Arrays.copyOf(factors, factors.length); 
} 
public BigInteger[] getFactors(BigInteger i) { 
if (lastNumber == null || !lastNumber.equals(i)) 
return null; 
else 
return Arrays.copyOf(lastFactors, lastFactors.length); 
} 
}
Caching the Last Result Using a Volatile Reference to an Immutable Holder Object. 
@ThreadSafe 
public class VolatileCachedFactorizer implements Servlet { 
private volatile OneValueCache cache = 
new OneValueCache(null, null); 
public void service(ServletRequest req, ServletResponse resp) { 
BigInteger i = extractFromRequest(req); 
BigInteger[] factors = cache.getFactors(i); 
if (factors == null) { 
factors = factor(i); 
cache = new OneValueCache(i, factors); 
} 
encodeIntoResponse(resp, factors); 
} 
}
Race conditions in accessing or updating multiple related variables can be eliminated by using an immutable object to 
hold all the variables. With a mutable holder object, you would have to use locking to ensure atomicity; with an 
immutable one, once a thread acquires a reference to it, it need never worry about another thread modifying its state. If 
the variables are to be updated, a new holder object is created, but any threads working with the previous holder still 
see it in a consistent state. 


To publish an object safely, both the reference to the object and the object's state must be made visible to other 
threads at the same time. A properly constructed object can be safely published by: 

•  Initializing an object reference from a static initializer; 
•  Storing a reference to it into a volatile field or AtomicReference; 
•  Storing a reference to it into a final field of a properly constructed object; or 
•  Storing a reference to it into a field that is properly guarded by a lock. 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值