并发下的对象的共享简述

现在发现自己平时不注意理论知识的整理和积累是多么不成熟的做法!一直觉得会开发出东西就足够了,但是现在觉得首先还是得有深层次的理论的积累!

以为做了几个web项目就能算作会开发了……结果发现被人问到 你对并发了解多少的时候就傻眼了:平时做的web项目好像都没有什么并发的情况! 呵呵 !

-------------------------------------分割线-------------------------------------

在并发程序中的使用和共享对象时,可以使用一些实用的策略,包括:

线程封闭。线程封闭的对象只能由一个线程拥有,对象被封闭在该线程中,并且只能由这个线程修改。

只读共享。在没有额外同步的情况下,共享的只读对象可以由多个线程并发访问,但任何线程都不能修改它。共享的只读对象包括不可变对象和事实不可变对象。

线程安全共享。线程安全的对象在其内部实现同步,因此多个线程可以通过对象的共有接口来进行访问而不需要进一步的同步。

保护对象。被保护的对象只能通过持有特定的锁来访问。保护对象包括封装在其他的线程安全对象中的对象,以及已发布的并且由某个特定锁保护的对象。

同步中的一个重要的概念:内存可见性(memory Visibility)。我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且希望确保当一个线程修改了对象状态之后,其他线程能够看到发生的状态变化。

加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。(对于volatile我以前是真不知道,也没用过,后面查了一下,当把变量声明为volatile之后,编译器与runtime都会注意到这个变量是共享的,因此不会将该变量上的操作和其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。 ps:我的理解 就是 每个线程再要使用到这个变量的时候都能够用到的是最新的值!)

这里主要说下线程封闭中的一种更为规范的使用方法:ThreadLocal。

ThreadLocal不是一个线程,而是一个Thread的局部变量。

  • This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
    Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

api里面原话,我以前没用过,今天也是看到这里了去看了下,也就是:为每一个使用该变量的线程提供一个独立的互不影响的该变量的副本(从线程的角度看,就是完全拥有该变量),这个副本在线程终结是被gc回收。

这里面个文章举得两个例子大概是能让人更加明白为什么要用它:http://blog.csdn.net/abing37/article/details/4460298

还有这个讲解的也已经比较详细了,http://www.jcwcn.com/article-30276-1.html

对ThreadLocal的解析:http://sishuok.com/forum/blogPost/list/340.html很详细!很强大!

我也看了下它的源代码,它是通过使用一个ThreadLocalMap的内部类,来完成副本的创建的,要详细了解还得看源码。

 ThreadLocal的使用 一般在:有些情况希望不同的线程保存的变量各自分开,那用这个还是比较合适的

先记下,研究了EJB再回头看:在是实现应用框架时大量使用了ThreadLocal。例如,在EJb调用期间,将j2ee容器需要将一个事务上下文(Transaction context)于某个执行中的线程关联起来。通过将事务上下文保存在静态的ThreadLocal对象中,可以很容易的实现这个功能:当框架代码需要判断当前运行的是哪个事务时。只需从这个ThreadLocal对象中读取事务上下文。这种机制很方便,因为它避免了在调用每个方法时都要传递执行上下文信息,然而这也将使用该机制的代码和框架耦合在一起。

ThreadLocal变量类似于全局变量,它能降低代码的可重用性,并在类之间引入隐含的耦合性,因此在使用时要格外小心。


总之,就是要保证该对象在多线程环境下 要么自身是安全的,要么使用它的过程是安全。

补充一下 :

ThreadLocal使用ThreadLocal作为key,通过set(T value)将value存储在每个使用它的线程的ThreadLocalMap中:

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
而ThreadlocalMap里面通过一个自定义的Entry类型的的数组来进行存储:

 static class Entry extends WeakReference<ThreadLocal> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal k, Object v) {
                super(k);
                value = v;
            }
        }
private Entry[] table;
ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值