欢迎进入Java社区论坛,与200万技术人员互动交流 >>进入
2)安全发布,如修复DLC问题.
1.private volatile IoBufferAllocator instance;
2.public IoBufferAllocator getInsntace(){
3. if(instance==null){
4. synchronized (IoBufferAllocator.class) {
5. if(instance==null)
6. instance=new IoBufferAllocator();
7. }
8. }
9. return instance;
10.}
3)开销较低的读写锁
1.public class CheesyCounter {
2. private volatile int value;
3.
4. public int getValue() { return value; }
5.
6. public synchronized int increment() {
7. return value++;
8. }
9.}
synchronized保证更新的原子性,volatile保证线程间的可见性.
volatile不能用于做什么?
1)不能用于做计数器
1.public class CheesyCounter {
2. private volatile int value;
3.
4. public int getValue() { return value; }
5.
6. public int increment() {
7. return value++;
8. }
9.}
因为value++其实是有三个操作组成的:读取、修改、写入,volatile不能保证这个序列是原子的.对value的修改操作依赖于value的最新值.解决这个问题的方法可以将increment方法同步,或者使用AtomicInteger原子类.
2)与其他变量构成不变式
一个典型的例子是定义一个数据范围,需要保证约束lower< upper.
1.public class NumberRange {
2. private volatile int lower, upper;
3.
4. public int getLower() { return lower; }
5. public int getUpper() { return upper; }
6.
7. public void setLower(int value) {
8. if (value > upper)
9. throw new IllegalArgumentException();
10. lower = value;
11. }
12.
13. public void setUpper(int value) {
14. if (value < lower)
15. throw new IllegalArgumentException();
16. upper = value;
17. }
18.}
尽管讲lower和upper声明为volatile,但是setLower和setUpper并不是线程安全方法.假设初始状态为(0,5),同时调用setLower(4)和setUpper(3),两个线程交叉进行,最后结果可能是(4,3),违反了约束条件.修改这个问题的办法就是将setLower和setUpper同步:
1.public class NumberRange {
2. private volatile int lower, upper;
3.
4. public int getLower() { return lower; }
5. public int getUpper() { return upper; }
6.
7. public synchronized void setLower(int value) {
8. if (value > upper)
9. throw new IllegalArgumentException();
10. lower = value;
11. }
12.
13. public synchronized void setUpper(int value) {
14. if (value < lower)
15. throw new IllegalArgumentException();
16. upper = value;
17. }
18.}
[1][2]
灯红酒绿的城市,登上楼顶,俯视万家灯火,