《Java并发编程实战》笔记--共享对象

来源:互联网 发布:多益网络官方客服电话 编辑:程序博客网 时间:2024/05/16 08:14
  1. Volatile变量
    它确保对一个变量的更新以可见的方式告知其他线程。当一个域声明为volatile类型后,编译器与运行时会监视这个变量:它是共享的,而且对于它的操作不会与其他的内存操作一起被重排序。volatile变量不会缓存在寄存器或者缓存在对其他处理器隐藏的地方。所以,读一个volatile类型的变量时,总会返回某一个线程所写入的最新值。

    volatile变量相对synchronized而言,只是轻量级的同步机制。加锁可以保证可见性与原子性;volatile变量只能保证可见性。
  2. ThreadLocal
    ThreadLocal允许你将每个线程与持有数值的对象关联在一起。ThreadLocal提供了get和set访问器,为每个使用它的线程维护一份单独的拷贝。所以,get总是返回由当前执行线程通过set设置的最新值。

    ThreadLocal变量通常用于防止在基于可变的单体(Singleton)或全局变量的设计中,出现(不正确)共享。例如:一个单线程化的应用程可能会维护一个全局的数据库连接,利用ThreadLocal存储JDBC连接,每个线程都会拥有属于自己的Connection。

  3. 不可变对象
    不可变对象创建后不能被修改,因而,不可变对象天生是线程安全的。

    只有满足如下状态,一个对象才是不可变的;

    • 它的状态不能在创建后在被修改;
    • 所有的域都是final类型;(从技术上讲,不可变对象的域并未全部声明为final类型,这样的情况是可能存在的,String就是这种类。)
    • 它被正确的创建(创建期间没有发生this引用的溢出)。
  4. 安全发布

示例:使用volatile发布不可变对象

public 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);    }}public class VolatileCachedFactorizer extends GenericServlet 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);    }    void encodeIntoResponse(ServletResponse resp, BigInteger[] factors) {    }    BigInteger extractFromRequest(ServletRequest req) {        return new BigInteger("7");    }    BigInteger[] factor(BigInteger i) {        // Doesn't really factor        return new BigInteger[]{i};    }}

安全发布的模式
为了安全的发布对象,对象的引用以及对象的状态必须同时对其他线程可见。一个正确创建的对象可以通过下列条件安全的发布:
·通过静态初始化器初始化对象的引用;
·将它的引用储存到volatile域或者AtomicReference;
·将它的引用储存到正确创建的对象的final域中;
·或者将它的引用储存到由锁正在保护的域中。

0 0
原创粉丝点击