请滑走,自用,无营养警告⚠

目录

【自旋锁 优 缺】

线程同步

Synchronized作用范围

线程之间的协作

synchronized和reentranklock的区别


独占锁:ReentrantLockSynchronized

共享锁:ReentrantReadWriteLock读共享写独占

private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

rwLock.writeLock().lock();  rwLock.writeLock().unlock();

rwLock.readLock().lock();rwLock.readLock().unlock();

公平锁线程按照申请锁的顺序来获取锁,先来先服务如果等待队列不为空,就加入队列。

【非公平锁】获取锁不按照申请锁的顺序,上来就直接尝试占有锁

吞吐量大性能高发出请求时,如果锁被其他线程持有,新的线程将被放入到队列中被挂起,但发出请求时恰好锁被释放了,跳过队列中所有的等待线程而获得锁。恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟(相当于人被叫醒需要时间)(新线程C很可能会在队列里的B被完全唤醒之前获得、使用以及释放这个锁,提高吞吐量)

优先级翻转,饥饿的线程(某个线程一直得不到锁)持有锁的时间相对较长或者请求锁的平均时间间隔较长,应该使用公平锁(插队可能不会提高吞吐量)

可重入锁递归锁 ReentrantLock / Synchronized

指的是同一线程外层函数获得锁之后,在进入内层方法会自动获取锁

线程可以进入任何一个它已经拥有的锁所同步的代码块作用避免死锁

验证ReentrantLock Synchronized 的代码

加两把锁,只解一把程序直接卡死,线程不能出来

自旋锁 优 缺

一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,不断的判断是否能获取锁,直到获取到锁才会退出循环。

优:获取不到锁不会阻塞,一直都是active,一直处于用户态减少了不必要的上下文切换,执行速度快

缺:while循环不断消耗CPU资源busy waiting

原来提到的比较并交换,底层使用的就是自旋,自旋就是多次尝试,多次访问,不会阻塞的状态就是自旋。

【为什么Synchronized无法禁止指令重排,却能保证有序性】

为了提升计算机能力,在硬件层面做了一些优化,如处理器优化和指令重排,但这些技术的引用带来了有序性问题。即使重排,也必须遵守as-if-serial语义,也就是在单线程中不能影响程序的执行结果。把单线程保护起来,给程序员一种幻觉:单线程是按代码的顺序来执行的

排他的、可重入的锁。当某个线程执行到一段被synchronized修饰的代码之前,会先进行加锁,执行完之后再进行解锁。在加锁之后,解锁之前,其他线程是无法再次获得锁的保证了同一时间内,被synchronized修饰的代码是单线程执行的。

线程同步

控制多个线程对共享资源的互斥访问,synchronized,ReentrantLock。

Synchronized作用范围

方法上  对象实例(this)||静态方法 对象对应的Class实例 || 对象实例 对应的代码块

ReentrantLock

除了能完成 synchronized 所能完成的所有工作外,还提供了诸如可响应中断锁、可轮询锁请求、定时锁等避免多线程死锁的方法。还可以与 Condition 类绑定,唤醒或等待指定条件线程。

线程之间的协作

join()在当前线程中调用另一个线程的 join() 方法,则当前线程会被挂起,转为阻塞状态而不是忙等待,直到另一个线程结束,当前线程再由阻塞状态变为就绪状态,等待 cpu 分配时间片。

适用场景:主线程生成并启动了子线程,需要用到子线程返回的结果,主线程需要在子线程结束后再结束

 

synchronized和reentranklock的区别

wait()、notify()   await()、signal()

synchronized属于JVM层面,ReentrantLock 是 JDK (juc)实现的。

monitorenter 只能在同步块 或 方法中 才能调用 wait/ notify

synchronized:不需要用户去手动释放锁,不用担心死锁

synchronized不可中断  ReentrantLock:可设置超时方法, 也可lockInterrupible()

非公平

ReentrantLock:精确唤醒

你可能感兴趣的:(面试)