芜湖哪里有做网站的,如保做网站赢利,wordpress 漏斗式搜索插件,dw 个人网站怎么做1、多线程中 synchronized 锁升级的原理是什么#xff1f;
synchronized 是JVM层面的锁#xff0c;是 Java 关键字#xff0c;通过 monitor 对象来完成#xff0c;synchronized 的实现涉及到锁的升级#xff0c;具体为无锁、偏向锁、自旋锁、重量级锁 synchronized 锁升级…1、多线程中 synchronized 锁升级的原理是什么
synchronized 是JVM层面的锁是 Java 关键字通过 monitor 对象来完成synchronized 的实现涉及到锁的升级具体为无锁、偏向锁、自旋锁、重量级锁 synchronized 锁升级原理在锁对象的对象头里面有一个 threadid 字段在第一次访问的时候 threadid 为空jvm 让其持有偏向锁并将 threadid 设置为其线程 id再次进入的时候会先判断 threadid 是否与其线程 id 一致如果一致则可以直接使用此对象如果不一致则升级偏向锁为轻量级锁只要有另一个竞争线程就升级通过自旋循环一定次数来获取锁执行一定次数之后如果还没有正常获取到要使用的对象此时就会把锁从轻量级升级为重量级锁此过程就构成了 synchronized 锁的升级。
锁的升级的目的锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实现方式使用了偏向锁升级为轻量级锁再升级到重量级锁的方式从而减低了锁带来的性能消耗。
升级成重量锁条件
老版本2个条件
第一个条件自旋次数超过10次时直接升级为重量级就是转圈赚了10次后直接升级重量级锁jvm有个参数 preSpinLock默认是10次可以自己设置第二个条件如果自旋线程的数量超过了cpu的二分之一也会直接升级为重量级锁比如你的cpu锁核数是8个但是有5个线程在那自旋等着占锁使用8的二分之一是45个线程明显已经超过了4所以这时候直接升级为重量级锁
新版本Adaptive CAS 自适应自旋让hotSpot自己决定自旋几次在升级为重量级锁就相当于自动化了也就不用我们去管了。所以以后jvm调优就不需要调整自旋次数的参数因为内部情况怎样只有jvm自己知道
2、Synchronized 与 ReentrantLock 的区别
1.1 底层实现的区别
synchronized 是JVM层面的锁是 Java 关键字通过 monitor 对象来完成synchronized 的实现涉及到锁的升级具体为无锁、偏向锁、自旋锁、重量级锁而 ReentrantLock 是由 java api 去实现的。ReentrantLock 实现则是通过利用CAS自旋机制保证线程操作的原子性和volatile保证数据可见性以实现锁的功能。
1.2 是否可手动释放
synchronized 不需要用户去手动释放锁synchronized 代码执行完后系统会自动让线程释放对锁的占用。ReentrantLock 则需要用户去手动释放锁如果没有手动释放锁就可能导致死锁现象。一般通过 lock() 和 unlock() 方法配合 try / finally 语句块来完成使用释放更加灵活。
1.3 是否可中断
synchronized 是不可中断类型的锁除非加锁的代码中出现异常或正常执行完成。ReentrantLock 则可以中断可通过 trylock(long timeout,TimeUnit unit) 设置超时方法或者将 lockInterruptibly() 放到代码块中调用 interrupt 方法进行中断。
1.4 是否公平锁
synchronized 为非公平锁。ReentrantLock 则即可以选公平锁也可以选非公平锁通过构造方法 new ReentrantLock 时传入 boolean 值进行选择为空默认 false 非公平锁true 为公平锁。
1.5 锁是否可绑定条件 Condition
synchronized 不能绑定。ReentrantLock 通过绑定 Condition 结合 await() / singal() 方法实现线程的精确唤醒而不是像 synchronized 通过 Object 类的 wait() / notify() / notifyAll() 方法要么随机唤醒一个线程要么唤醒全部线程。
1.6 锁的对象
synchronzied 锁的是对象锁是保存在对象头里面的根据对象头数据来标识是否有线程获得锁 / 争抢锁。ReentrantLock 锁的是线程根据进入的线程和 int 类型的 state 标识锁的获得 / 争抢。
原文链接https://blog.csdn.net/liuwg1226/article/details/120164119
3、synchronized和lock有什么区别
1synchronized 是JVM层面的锁是 Java 关键字通过 monitor 对象来完成synchronized 的实现涉及到锁的升级具体为无锁、偏向锁、自旋锁、重量级锁而Lock是java.util.concurrent.Locks 包下的一个接口2Synchronized 使用过后会自动释放锁而Lock需要手动上锁、手动释放锁。在 finally 块中3synchronized 关键字不能响应中断Lock可以响应中断、可定时4synchronized关键字是非公平锁即不能保证等待锁的那些线程们的顺序而Lock的子类ReentrantLock默认是非公平锁但是可通过一个布尔参数的构造方法实例化出一个公平锁5synchronized无法判断是否已经获取到锁而Lock通过tryLock()方法可以判断是否已获取到锁6Lock可以通过分别定义读写锁提高多个线程读操作的效率。7二者的底层实现不一样synchronized是同步阻塞采用的是悲观并发策略Lock是同步非阻塞采用的是乐观并发策略底层基于volatile关键字和CAS算法实现
4、公平锁、非公平锁、可重入锁、独占锁
公平锁是指在分配时候考虑线程排队等待的情况优先将该锁分配给排队时间最长的线程非公平锁指在分配时候不考虑线程排队等待的情况直接尝试获得锁在获取不到锁时候再排队到队尾等待可重入锁也叫递归锁指在同一个线程中在外层函数获得该锁之后内层的递归函数依旧可以继续获取该锁独占锁指该锁在同一个时间只能被同一个线程获得而获得锁的其他线程只能在同步队列中等待
5、Volatile如何保证可见性
Volatile有两个特性
一种是保证该变量对所有的线程可见一种是禁止指令重排即Volatile变量不会被缓存在寄存器或是对其他处理器不可见的地方
volatile修饰的变量JMM将在写操作后插入一个写屏障指令在读操作前插入一个读屏障指令这代表着
一旦对变量写入了新值任何访问这个变量的线程都会得到新的值在写入前也会保证所有之前发生的事情已经发生并且更新过的数据值也是可见的。内存屏障会把之前的写入值都刷新到主内存
所以Volatile可以保证可见性
6、说说java内存模型
java内存模型(JMM)是线程间通信的控制机制.JMM定义了主内存和线程之间抽象关系。线程之间的共享变量存储在主内存中每个线程都有一个私有的本地内存本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念并不真实存在。它涵盖了缓存写缓冲区寄存器以及其他的硬件和编译器优化。
7、死锁的发生原因和怎么避免
死锁简单来说就是两个或者两个以上的线程在执行的过程中争夺同一个共享资源造成的相互等待的现象。如果没有外部干预线程会一直阻塞无法往下执行这些一直处于相互等待资源的线程就称为死锁线程。
导致死锁的条件有四个也就是这四个条件同时满足就会产生死锁。
互斥条件共享资源 X 和 Y 只能被一个线程占用请求和保持条件线程 T1 已经取得共享资源 X在等待共享资源 Y 的时候不释放共享资源 X不可抢占条件其他线程不能强行抢占线程 T1 占有的资源循环等待条件线程 T1 等待线程 T2 占有的资源线程 T2 等待线程 T1 占有的资源就是循环等待。
按照死锁发生的四个条件只需要破坏其中的任何一个就可以解决但是互斥条件是没办法破坏的因为这是互斥锁的基本约束其他三方条件都有办法来破坏
1、设置超时时间超时可以退出防止死锁
2、降低锁的使用粒度尽量不要几个功能用同一把锁
3、我们可以一次性申请所有的资源这样就不存在等待了
8、CAS、CAS自旋等待、ABA问题
CAS指比较并交换CAS算法CAS(V,E,N)包含三个参数,V表示要更新的变量 E 表示预期的值 N 表示 新值。当要更新的变量等于预期的值才会把要更新的变量设置为新值CAS操作采用了乐观锁的思想
CAS自旋等待在原子包concurrent提供了一组原子类这些原子类的基本特性是在多线程的环境下在有多个线程同时执行这些类的实列包含的方法时候会有排他性。其内部便是基于CAS算法实现的即在某个线程进入方法中执行其中的指令时候不会被其他线程打断而别的线程就像自旋锁一样一直等到该方法执行完才由jvm从等待的队列中选择另外一个线程进入。
ABA问题在需要取出内存中某时刻的数据然后再下一个时候进行比较替换如果在这个时间差内可能数据已经发生改变可能导致ABA问题。即第1个线程从V取出A这时第2个线程也从内存V中取出A并将V位置的数据A先修改成B接着又把数据修改成A 第一个线程在进行CAS操作的时候发现V位置的数据是A第一个线程操作成功。尽管第一个线程角度CAS操作是成功但实际上的数据发生了变化某些情况下可能引起过程数据不一致的问题。可以通过版本号来解决这个问题
9、什么是AQS
AQS是一个抽象的队列同步器通过维护一个共享的资源状态和一个先进先出的线程等待队列来实现一个多线程访问共享资源的同步框架
AQS为每个共享资源都设置了一个共享资源锁线程在需要访问共享资源时首先需要获得共享资源锁如果获取到了共享资源锁既可以在当前线程使用该共享资源如果获取不到则将该线程放入等待队列中等待下次调度
AQS定义了两种资源共享的方式独占式和共享式
独占式只有一个线程可以执行如ReentrantLock,原理是ReentrantLock中的state初始值为0表示无锁状态在线程执行tryAcquire()获取该锁后state1这是该线程独占ReentrantLock锁其他线程在通过tryAcquire()获得锁时候都会失败直到该线程释放后state再次为0共享式多个线程可以同时执行如countDownLatch等