• 怎样才是线程安全的?


    一、final 一下

    final 关键字,具有不可变性。所以并发中对于其的使用时线程安全的。

    final 可以修饰变量,方法及类对象。

    不可变:不可被修改,不可被继承,不可被覆盖,重写等。

    二、加锁

    锁的本质就是一个同步块,处于同步块儿中的操作可以认为是线程安全的。

    那怎么加锁呢?

    1、synchronized 关键字

    底层其实对应的是用monitorenter及monitorexit字节码指令包裹需要同步的执行。

    monitorenter

    ... ...

    monitorexit 

    同一个线程对同一个同步块的加锁,只会执行一次,当获取到锁后,再次进入同步块时,则不需要再次进行加锁,我们称之为“可重入”,当然,重入也会被记录,

    线程对对象的加锁标识,存在于对象的头信息中,具体可以了解下:偏向锁、轻量锁、重量所,锁膨胀相关知识。

    对于静态执行的锁:锁类对象。

    对于费静态执行的锁:锁类实例。

    2、lock:

    我们称之为可重入锁。

    可重入,也就是我们上面所说的,在获锁期间,可以重复进入。

    相对于synchronized来说,lock更加灵活:可中断,可超时,公平锁等。

    lock的实现基于AQS。

    基本使用:

    try {

    lock();

    ... ...

    } finally {

        unlock();

    }

    特别需要注意的一点是一定要保证unlock。

    三、局部变量

    局部变量,其实实操对应的是线程私有栈中的变量操作。因为私有,所以是线程安全的。

    线程栈具体参考:Java虚拟机栈 

    局部变量以栈帧的形态参与实际的运行计算。

    四、锁优化

    1、CAS自旋:

    CAS:Compare And Swap 对比然后交换值,CAS 属于硬件指令级别,因此本身可以保证原子性。

    自旋:CAS操作中会有个期望值的限制,达不到这个预期,则执行不成功。因此期望最终能够执行,则需要多次尝试,也就是所谓的“自旋”,循环尝试。

    例如,对于普通的“++”操作,是非线程安全的,而要达到线程安全的+1目的,就必须添加必要的同步性保障,或者,使用此处我们所论述的CAS特性。

    示例:AtomicInteger::getAndIncrement

    内部通过 Unsafe 实例的 compareAndSwapInt 方法实现。

    2、轻量锁

    单一线程访问加锁优化;对象头信息 Mark Word;前提---对于绝大多数锁,在整个同步周期内是不存在竞争的;无竞争情况下,使用CAS操作消除同步使用的互斥量。

    执行过程:
     
    进入同步块,对象未加锁(锁标志位 01)
    |
    线程栈帧中建立一个所记录(Lock Record)空间(存储锁对象Mark Word 拷贝:Displaced Mark Word)
    |
    虚拟机尝试使用CAS操作,将对象的Mark Word更新为指向Lock Reord的指针
    |
    更新成功,线程拥有对象锁,对象Mark Word锁标志位变为 00
    |
    更新失败,则检查对象Mark Word是否指向当前线程
    |
    是的话,则说明已经拥有了轻量级锁,继续同步块操作
    |
    否的话,则说明对象已经被其它线程占有,两个及以上线程征用同一个锁,则膨胀为重量级锁,所标志位变为10,Mark Word存储的是指向重量级锁()的指针
     
    解锁:CAS 将线程的复制的Displace Mark Word和对象的Mark World替换回来。

    3、偏向锁

    无竞争情况下,消除整个同步块。偏向于第一个获得锁的线程。

    对象锁第一次被线程获取的时候,虚拟机把对象头的标志位设为01,偏向模式,同时使用CAS模式把获取到这个锁的线程ID写入对象的Mark Word中
    |
    获取锁成功,持有偏向锁的线程每次进入锁的相关同步块,虚拟机都可以不再进行任何同步操作。
    |
    另外线程尝试获取此所,则偏向模式结束,撤下偏向(Revoke Bias),恢复未锁定(00)或者轻量级锁定(10)。

    4、锁粗化

    选择合适的粒度层级进行加锁同步。

    5、锁消除

    如果一段代码中,堆上的所有数据都不会逃逸出去而被其它线程访问到,当作栈上数据对待,消除锁。

    等等。

  • 相关阅读:
    Blank page instead of the SharePoint Central Administration site
    BizTalk 2010 BAM Configure
    Use ODBA with Visio 2007
    Handling SOAP Exceptions in BizTalk Orchestrations
    BizTalk与WebMethods之间的EDI交换
    Append messages in BizTalk
    FTP protocol commands
    Using Dynamic Maps in BizTalk(From CodeProject)
    Synchronous To Asynchronous Flows Without An Orchestration的简单实现
    WSE3 and "Action for ultimate recipient is required but not present in the message."
  • 原文地址:https://www.cnblogs.com/niejunlei/p/12863360.html
Copyright © 2020-2023  润新知