`

java中的锁

    博客分类:
  • java
 
阅读更多

1.重入锁 自旋锁 死锁

3.1定义: 当持1个线程的锁 再次获取锁时不会被锁住

3.2自旋锁:线程空转CPU(不会去堵塞等待其他线程唤醒)获取锁

3.3死锁:1个线程在等待另外一个等待的线程

While( true) {

}   // 空转CPU

2.线程安全性问题

3.4活跃性问题

死锁 

    2个线程彼此持有对方的需要的锁  

1 线程A拥有 对象锁1 同时等待线程B释放对象锁2

2 线程B拥有 对象锁2 同时等待线程A释放对象锁1

饥饿

    线程一直获取不到CPU运行时间的机会 

 总结原因有3 

  1 高优先级线程吞噬了低优先级线程的时间

  2 线程被堵塞在等待区

  3 线程在等待的对象也处理wait状态 导致现在一直等待

解决办法 使用锁而不用synchronize 使用公平锁保证指定的线程被notify

公平锁的大概实现原理:每一个线程都和一个QuenenObject对象相关联从而保证线程能被指定的唤醒同时能被保证指定的堵塞(一个线程在等待的对象也处在等待状态)

活锁

    

多线程一定快吗?

单核CPU存在多线程 会存在上下文切换 会有一定的资源消耗

AbstractQuenendSynchronizer(AQS)

3.线程安全性总结

3.1出现线程安全性条件

     

3.5解决线程安全性的途径 

注意:1偏向锁是在只有一个锁的情况下才使用的,轻量级锁是在多线程交替执行时才使用的如果存在多个线程同时竞争一个锁轻量级线程就会升级为重量级锁 Synchronized依赖于底层操作系统的mutex Lock来实现的 用户在使用时会从用户态到核心态会消耗CPU资源,为了减少重量级锁获取和释放带来的资源消耗 jdk6引入了 偏向锁 和轻量级锁                                   锁的其他优化:1 适应性自旋 2 锁消除 3锁粗化

1.使用synchronized(jdk6偏向锁 轻量级锁 重量级锁)关键字 、

 偏向锁:偏向锁首先会判断锁标识位是否是偏向锁 如果是判断线程ID是否指向当前线如果是就进入同步代码块,如果不是就通过CAS去竞争锁 如果当前线程竞争到了锁就直接进入到同步代码块 否则获取到偏向锁的线程被挂起,锁升级为轻量级锁 被阻塞在安全点的线程执行同步代码块

 

 轻量级锁

  加锁的过程:1 判断对象Mark Word是01表示对象无锁,虚拟机会在当前线程的栈帧中建立一个Lock Record的空间 用于存储锁对象的Mark Word的拷贝,官方成为displaced mark record    2 拷贝对象头的Mark Word到Lock Record中去 3 更新mark Word为Lock Record的指针 并将Lock Record的owner指向object 如果更新成功就进入到 4 否则进入到5              4如果更新成功就表示这个MarkWord的锁状态为00(轻量级锁) 表示该线程拥有了锁      5 如果更新失败就检查mark word是否指向了当前线程 如果指向就代表当前线程已经拥有了锁,线程就进入到同步执行块 否则就是多个线程进行了竞争 锁进行升级为重量级锁后来进来的线程被堵塞

注意:轻量级锁和偏向锁减少了锁的释放和获取消耗的CPU资源 只有线程竞争非常激烈时才会去进行线程堵塞 随后OS调用进行唤醒操作

  解锁的过程:

重量级锁:

2. 使用volitale关键字(只能保证可见性 不能保证原子性)

3.使用jdk提供的原子类

4.使用Lock

3.6认识的”*锁”

4.线程wait notify(线程之间的通信) 

  线程之间的通信解决的是线程之间的协作

Wait会释放锁 notify会随机一个线程再次获取锁 notifyAll会所有线程获取锁  

Wait 和notify都会关联一个相同的对象的监视器锁对象

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics