阅读《java并发编程实战》第三章

阅读《java并发编程实战》第三章

第一个例子,没有重现

public class NoVisibility {
    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
            while (!ready) {
                Thread.yield();
            }
            System.out.println(number);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ReaderThread().start();
        
		// 加入睡眠让子线程启动好,也无法重现
        // Thread.sleep(1000);

        number = 42;
        ready = true;
    }
}
// 结果:
    // 程序能正常结束,输出42。没有展示出可见性的问题。

例子:可变正数类

@NotThreadSafe
class MutableInteger {
    private int value;
    
    public int get() { return value; }
    public void set(int value) { this.value = value; }
}
// 通过添加synchronized锁,对get/set都要加
@ThreadSafe
class MutableInteger {
    private int value;

    public synchronized int get() { return value; }
    public synchronized void set(int value) { this.value = value; }
}

要点:加锁(内置锁或Lock)能保证可见性。当线程B执行由锁保护的同步代码块时,可以看到线程A之前在同一个同步代码块中的所有操作结果。【加锁的含义不仅仅局限于互斥行为,还包括内存的可见性】

要点2:volatile变量,是java语言提供的一个稍弱的同步机制,确保变量的更新操作通知到其他线程。
从内存可见性角度来看,写入volatile变量相当于退出同步代码块,而读取volatile变量就相当于进入同步代码块。

要点3:发布(publish)一个对象是指,使对象能在当前作用域之外的代码中使用。例如:将一个对象引用保存到其他代码可以访问的地方;或者在某个非私有得方法中返回该引用;或者将引用传递到其他类的方法中。

// 发布对象举例
class UnsafeStates {
    private String[] states = {"AK", "AL"};
    public String[] getStates() {
        return states;
    }
}

class Demo {
    public static Set<Secret> knownSecrets;
    
    public void initialize() {
        knownSecrets = new HashSet<Secret>();
    }
}

3-12, 3-13:

@Immutable
class OneValueCache {
    private final BigInteger lastNumber;
    private final BigInteger[] lastFactors;

    public OneValueCache(BigInteger lastNumber, BigInteger[] lastFactors) {
        this.lastNumber = lastNumber;
         // 有问题,没有对lastFactors做null判断
        this.lastFactors = Arrays.copyOf(lastFactors, lastFactors.length);
    }

    public BigInteger[] getFactors(BigInteger i) {
        if (lastNumber == null || !lastNumber.equals(i)) {
            return null;
        }
        return Arrays.copyOf(lastFactors, lastFactors.length);
    }
}

@ThreadSafe
class VolatileCachedFactorizer implements Servlet {
    private volatile OneValueCache cache = new OneValueCache(null, null);
    
    public void sevice(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);
    }
}
posted @ 2023-05-27 17:16  编程爱好者-java  阅读(6)  评论(0编辑  收藏  举报