做网站后台运营这个工作怎么样,抚州教育网站建设,wordpress 采集 入库,广州seo黑帽培训公平锁和非公平锁只有两处不同#xff0c;总结#xff1a;
1、非公平锁在调用 lock 后#xff0c;首先就会调用 CAS 进行一次抢锁#xff0c;如果这个时候恰巧锁没有被占用#xff0c;那么直接就获取到锁返回了。
2、非公平锁在 CAS 失败后#xff0c;和公平锁一样都会进…公平锁和非公平锁只有两处不同总结
1、非公平锁在调用 lock 后首先就会调用 CAS 进行一次抢锁如果这个时候恰巧锁没有被占用那么直接就获取到锁返回了。
2、非公平锁在 CAS 失败后和公平锁一样都会进入到 tryAcquire 方法在tryAcquire方法中如果发现锁这个时候被释放了state 0
非公平锁会直接 CAS 抢锁但是公平锁会判断等待队列是否有线程处于等待状态如果有等待则不去抢锁乖乖排到后面。公平锁和非公平锁就这两点区别如果这两次 CAS 都不成功那么后面非公平锁和公平锁是一样的都要进入到阻塞队列等待唤醒。
相对来说非公平锁会有更好的性能因为它的吞吐量比较大。
当然非公平锁让获取锁的时间变得更加不确定可能会导致在阻塞队列中的线程长期处于饥饿状态。二、Condition
其中Lock替代了 synchronized 方法和语句的使用【Condition】 替代了 Object 【监视器】方法的使用
我们以往开发需要用到锁, 并且要用到睡眠和唤醒就只有synchronized, 但是【ReentrantLock】也实现了Lock实现了锁Condition还实现了睡眠和唤醒的功能。 ConditionObject主要是为并发编程中的同步提供了等待通知的实现方式可以在不满足某个条件的时候挂起线程等待。直到满足某个条件的时候在唤醒线程。
synchronized的缺点
1、synchronized的 notify() 方法一次只能唤醒一个线程而且唤醒线程的方式是随机的从处于等待集中随机选取一个线程唤醒。
并且是唤醒等待队列中优先级最高的线程。
2、notify()可能会导致死锁原因是notify唤醒了线程A可能要获取的锁此时已经被别的线程获取了那么线程A一直在阻塞
而线程A获得锁这个锁对应的阻塞队列里面的其他线程永远得不到执行。正确的使用场景是WaitSet中等待的条件是相同 确保唤醒任意一个都能够执行后面的事项。
如果被唤醒的线程无法正确处理务必继续notify()下一个线程并且自身要回到WaitSet等待集中。那就要用到下面2个方法他们可以控制具体线程的唤醒和阻塞但是不释放锁。
LockSupport.park(this) 阻塞但是不释放锁。
LockSupport.unpark(thread对象) 唤醒指定的线程。
与之对应的还有下面的2个方法
Thread.sleep(n) 不会释放占有的锁但是会让出cpu执行权到时自动唤醒然后抢cpu的执行权。
Object.wait(n) 会释放占有的锁,没传时间就一直睡眠需要其他线程调用Object对象notify方法。加了时间自动醒进到阻塞队列再来重新获取锁。object.wait和thread.wait区别
每个类都继承了Object类Object有个非静态的方法wait所以要调用wait必须先有实例对象才能调用wait方法。
Thread类也继承了Object类。
只有object.wait这么调用的没有见过thread.wait,因为调用wait方法必须要持有这个对象的锁不然会报错我们要拿到一个对象的锁
就要使用synchronized来锁住对象。 我们也不会把线程对象thread当做我们的并发锁三、synchronized加锁原理
每个对象都关联了一个监视器线程可以对其进行【加锁和解锁】操作。在同一时间只有一个线程可以拿到对象上的监视器锁。
如果其他线程在锁被占用期间试图去获取锁那么将会【被阻塞】直到成功获取到锁。
同时【监视器锁可以重入】也就是说如果线程 T 拿到了锁那么线程T可以在解锁之前重复获取锁每次解锁操作会反转一次加锁产生的效果synchronized 代码块。synchronized(object) 在对某个对象上执行加锁时会尝试在该对象的监视器上进行加锁操作
只有成功获取锁之后线程才会继续往下执行。线程获取到了监视器锁后将继续执行 synchronized 代码块中的代码如果代码块执行完成
或者抛出了异常线程将会自动对该对象上的【监视器执行解锁】操作。synchronized 作用于方法称为同步方法。同步方法被调用时会自动执行加锁操作只有加锁成功方法体才会得到执行。
如果被 synchronized 修饰的方法是实例方法那么这个实例的监视器会被锁定。
如果是 static 方法线程会锁住相应的 Class 对象的监视器。
方法体执行完成或者异常退出后会自动执行解锁操作。小知识点对 【Class】加锁、对【对象】加锁它们之间不构成同步。synchronized 作用于静态方法时是对 Class 对象加锁作用于实例方法时是对实例加锁。 面试中经常会问到一个类中的两个 synchronized static 方法之间是否构成同步构成同步。
【等待状态】是指进程由于某种条件不具备在等待队列中排队等待cpu对它进行调度。 【阻塞状态】可能是由于竞争共享资源的情况下没有得到锁或信号量的条件不满足而在临界区之外被暂停执行了。
文章地址
Condition使用案例
CountDownLatch主要功能是一个计数器主要countDown()和wait()方法1、一开始创建CountDownLatch对象需要指定一个数字这个数字和公平锁里面的state一样比如100就表示某个锁被重入了100次
所以需要释放一百次countDown就类似于释放一次锁的意思所以countDown方法要放在子线程里面执行子线程完成一次任务就减一。2、什么场景要调用wait()呢比如启动服务需要启动创建N个组件创建了一个组件就countDown()我们只需要在线程池外面wait就可以了
就等status变成0就可以了如果没有变成0那么调用wait的线程就会【阻塞】并且进到阻塞队列为什么会进到阻塞队列
因为假如这个CountDownLatch对象是多个线程共享那么多个线程都想知道status什么时候变成0所以只要是通过CountDownLatch调用wait那
么就会阻塞那么多个线程阻塞总得排队多个线程调用wait都有可能阻塞进到队列那么什么时候唤醒这些阻塞队列就是等state变成0
然后通过自旋的方式从阻塞队列里面把所有Node取出来挨个唤醒。