A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 鲍霄霄 中级黑马   /  2012-7-16 11:08  /  1015 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

[size=0.76em]这些是我查找资料与自己的总结 感觉不错大家看看
1. 同步方法或同步代码块?
[size=0.76em]您可能偶尔会思考是否要同步化这个方法调用,还是只同步化该方法的线程安全子集。在这些情况下,知道 Java 编译器何时将源代码转化为字节代码会很有用,它处理同步方法和同步代码块的方式完全不同。
[size=0.76em]当 JVM 执行一个同步方法时,执行中的线程识别该方法的 method_info 结构是否有 ACC_SYNCHRONIZED 标记设置,然后它自动获取对象的锁,调用方法,最后释放锁。如果有异常发生,线程自动释放锁。
[size=0.76em]另一方面,同步化一个方法块会越过 JVM 对获取对象锁和异常处理的内置支持,要求以字节代码显式写入功能。如果您使用同步方法读取一个方法的字节代码,就会看到有十几个额外的操作用于管理这个功能。清单 1 展示用于生成同步方法和同步代码块的调用:

清单 1. 两种同步化方法
                                package com.geekcap;public class SynchronizationExample {    private int i;    public synchronized int synchronizedMethodGet() {        return i;    }    public int synchronizedBlockGet() {        synchronized( this ) {            return i;        }    }}

[size=0.76em]synchronizedMethodGet() 方法生成以下字节代码:
        0:        aload_0        1:        getfield        2:        nop        3:        iconst_m1        4:        ireturn

[size=0.76em]这里是来自 synchronizedBlockGet() 方法的字节代码:
        0:        aload_0        1:        dup        2:        astore_1        3:        monitorenter        4:        aload_0        5:        getfield        6:        nop        7:        iconst_m1        8:        aload_1        9:        monitorexit        10:        ireturn        11:        astore_2        12:        aload_1        13:        monitorexit        14:        aload_2        15:        athrow

[size=0.76em]创建同步代码块产生了 16 行的字节码,而创建同步方法仅产生了 5 行。

[size=0.76em]回页首
[size=0.76em]2. ThreadLocal 变量
[size=0.76em]如果您想为一个类的所有实例维持一个变量的实例,将会用到静态类成员变量。如果您想以线程为单位维持一个变量的实例,将会用到线程局部变量。ThreadLocal 变量与常规变量的不同之处在于,每个线程都有其各自初始化的变量实例,这通过 get() 或 set()方法予以评估。
[size=0.76em]比方说您在开发一个多线程代码跟踪器,其目标是通过您的代码惟一标识每个线程的路径。挑战在于,您需要跨多个线程协调多个类中的多个方法。如果没有 ThreadLocal,这会是一个复杂的问题。当一个线程开始执行时,它需要生成一个惟一的令牌来在跟踪器中识别它,然后将这个惟一的令牌传递给跟踪中的每个方法。
[size=0.76em]使用 ThreadLocal,事情就变得简单多了。线程在开始执行时初始化线程局部变量,然后通过每个类的每个方法访问它,保证变量将仅为当前执行的线程托管跟踪信息。在执行完成之后,线程可以将其特定的踪迹传递给一个负责维护所有跟踪的管理对象。
[size=0.76em]当您需要以线程为单位存储变量实例时,使用 ThreadLocal 很有意义。

[size=0.76em]回页首
[size=0.76em]3. Volatile 变量
[size=0.76em]我估计,大约有一半的 Java 开发人员知道 Java 语言包含 volatile 关键字。当然,其中只有 10% 知道它的确切含义,有更少的人知道如何有效使用它。简言之,使用 volatile 关键字识别一个变量,意味着这个变量的值会被不同的线程修改。要完全理解volatile 关键字的作用,首先应当理解线程如何处理非易失性变量。
[size=0.76em]为了提高性能,Java 语言规范允许 JRE 在引用变量的每个线程中维护该变量的一个本地副本。您可以将变量的这些 “线程局部” 副本看作是与缓存类似,在每次线程需要访问变量的值时帮助它避免检查主存储器。
[size=0.76em]不过看看在下面场景中会发生什么:两个线程启动,第一个线程将变量 A 读取为 5,第二个线程将变量 A 读取为 10。如果变量 A 从 5 变为 10,第一个线程将不会知道这个变化,因此会拥有错误的变量 A 的值。但是如果将变量 A 标记为 volatile,那么不管线程何时读取 A 的值,它都会回头查阅 A 的原版拷贝并读取当前值。
[size=0.76em]如果应用程序中的变量将不发生变化,那么一个线程局部缓存比较行得通。不然,知道 volatile 关键字能为您做什么会很有帮助。

[size=0.76em]回页首

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马