Java线程安全与锁优化

一、Java语言中的线程安全
     Java语言中各种操作共享数据分为:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。

不可变:不可变的对象一定是线程安全的。基本数据类型,在定义时使用final修饰它就可以保证不可变,对象类型,把对象中带状态的变量都声明为final,这样构造函数结束后,它就是不可变的。
绝对线程安全:不管运行时环境如何,调用者都不需要任何额外的同步措施。Vector举例,多线程并发时,并不安全。
相对线程安全:保证这个对象,单独操作是线程安全的,我们在调用的时候需要做额外的保障措施,Vector,比如HashTable,Collections的synchronizedCollection
线程兼容:对象本身不是线程安全的,可以在调用端通过使用同步手段保证对象在并发环境中可以安全的使用,比如Arraylist、HashMap。
线程对立:无论采用什么手段,都无法保证对象在多线程并发环境中保证线程安全。

二、线程安全的实现方法
 1、互斥同步:阻塞同步,通过关键字synchronized,会在同步块前加monitorenter、monitorexit这两个字节码指令。执行monitorenter指令时,首先尝试获取对象的锁,如果对象没有被锁定或者对象已被锁定,把锁的计数器加1,在执行monitorexit指令时,操作计数器减1,当计数器为0时,锁就被释放,如果获取锁失败,那当前线程就要阻塞等待,直到锁对象被另外一个线程释放为止。
 ReentrantLock:具备线程重入特性,有等待可中断,可实现公平锁,以及锁可以绑定多个条件。
等待可中断:是指当持有锁的线程长期不释放锁的时候,正在等待的线程可以放弃等待,去处理其他的事情。
公平锁:是指多个线程在等待同一个锁时,必须按照申请锁的时间先后顺序依次来获得锁,非公平锁:在锁被释放时,任何一个等待的锁都有机会获得锁。synchronized锁是非公平锁,ReentrantLock默认是非公平锁,可以带boolean指,为公平锁。
锁可以绑定多个条件。
2、非阻塞同步

二、锁优化
      锁包括自旋锁与自适应锁,锁消除、锁粗化,轻量级锁、偏向锁。
      自旋锁:并发时,请求锁,稍等一下,但不放弃处理器的执行时间,看看持有锁的线程是否会很快释放锁,如果锁占用时间短,自旋等待的效果较好,否则,白白浪费处理器的时间,自旋的次数默认10次。
      自适应锁:就是自适应的自旋锁,自旋的时间不固定了,根据历史获取锁的情况,自动决定是否要自旋等待,若果一个锁很多次不能通过自旋获得锁,下次可能就直接挂起而不是自旋等待。
      锁消除:对一些代码上要求同步,但是检测到不可能存在共享数据竞争的锁进行消除。
      锁粗化:如果一系列连续的操作都对同一个对象反复枷锁和解锁,就会采用锁粗化,将锁的范围扩大。
     轻量级锁:无竞争的情况下,使用CAS操作去消除同步使用的互斥量。
     偏向锁:无竞争的情况下,把整个同步都消除掉,CAS操作也不做了。

  

你可能感兴趣的:(Java线程安全与锁优化)