JAVA 并发真讨厌
互联网行业随着商业化,信息化,快速发展至今,借助人口大国和时代催生,早已到了秀才不出门便知天下事的年代,80后吃饭就着菜,90后吃饭就着肉,00后吃饭就着paid,多媒体,小视频,流量明星,随着5G的普及,互联网将跨入新时代。
人口多,那么带给互联网就少不了高并发,什么叫高并发?单位时间内处理的请求量叫做高并发。高并发就离不开多线程操作。
既然是高并发,就对应了JUC包的API类。着重挑一些听得多的记录一下。
1.最常问:synchronized和Lock有什么区别?
①:synchronized是JVM层面实现的,java提供的关键字,Lock是API层面的锁。
②:synchronized不需要手动释放锁,底层会自动释放,
Lock则需要手动释放锁,否则有可能导致死锁
③:synchronized等待不可中断,除非抛出异常或者执行完成
Lock可以中断,通过interrupt()可中断
④: synchronized是非公平锁
Lock是默认公平锁,当传入false时是非公平锁
⑤:synchronized不可绑定多个条件
Lock可实现分组唤醒需要唤醒的锁
2. synchronized在修饰方法和修饰代码块的区别?
字节码结果不同
3.偏向锁对synchronized和ReentrantLock的价值?
UseBiaseLocking对synchronize有用
ReentrantLock已经实现了偏向锁UseBiaseLocking java5 6版本
4.当主线程退出时,守候子线程会执行完毕吗?
不一定执行 ti.setDaemon(true);
守候线程执行依赖于执行时间
5.请说明 ShutdownHook 线程的使用场景,以及如何触发执行?
**优雅的停止线程**
Runtime runtime=new Runtime();runtime.addShutDownHook(new Thread(()->{System.out.println("")),"");
6.最常见CAS和AQS的理解?
在Lock中常常听到CAS以及AQS的名词,根据个人理解整理下相关知识
CAS:compare and swap 比较并交换,判断取出内存中某时刻的数据并在当下时刻进行交换,缺点:循环时间长,只能保证一个共享变量的原子操作,引来ABA问题?
看下源码:
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
CAS核心是由native修饰的Unsafe类,其中valueOff为内存偏移量地址,变量由volatile修饰。
/** * Atomically increments by one the current value. * * @return the previous value */ public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); }
AQS:AbstractQueuedSynchronizer,AQS是ReentrantLock的核心实现,将其比为一个框架
源码:
final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; }
看下本类
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements java.io.Serializable {
private static final long serialVersionUID = 7373984972572414691L;
/** * Creates a new {@code AbstractQueuedSynchronizer} instance * with initial synchronization state of zero. */ protected AbstractQueuedSynchronizer() { }...
}
提供方法很多
CAS如果看做是一个算法的话,AQS可以视为一个框架,
/** * Acquires in exclusive mode, ignoring interrupts. Implemented * by invoking at least once {@link #tryAcquire}, * returning on success. Otherwise the thread is queued, possibly * repeatedly blocking and unblocking, invoking {@link * #tryAcquire} until success. This method can be used * to implement method {@link Lock#lock}. * * @param arg the acquire argument. This value is conveyed to * {@link #tryAcquire} but is otherwise uninterpreted and * can represent anything you like. */public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
传入arg参数,默认为0,以独占模式获取,忽略中断。通过至少调用一次实现
7:CountDownLatch 与 CyclicBarrier 和Semaphore的区别?
CountdownLatch等待所有线程计数器变为0执行一系列操作后唤醒,
CyclicBarrier 可循环屏障,所有被屏障拦截的的线程完毕才会干活,相当于i++,但这样理解是不正确的,因为CyclicBarrier的await()实际是做了–i操作。
private int dowait(boolean timed, long nanos) throws InterruptedException, BrokenBarrierException, TimeoutException { final ReentrantLock lock = this.lock; lock.lock(); try { final Generation g = generation;
if (g.broken) throw new BrokenBarrierException();
if (Thread.interrupted()) { breakBarrier(); throw new InterruptedException(); }
int index = --count; if (index == 0) { // tripped boolean ranAction = false; try { final Runnable command = barrierCommand; if (command != null) command.run(); ranAction = true; nextGeneration(); return 0; } finally { if (!ranAction) breakBarrier(); } }
Semaphore:信号量,控制并发线程数,指定线程执行。
未完待续...
声明:本文内容根据B站UP主**mercyblitz,**2019.4.07期视频以及历史资料整理,扫描二维码关注小马哥公众号,java劝退师,好东西需要分享,干货满满
- 点赞
- 收藏
- 关注作者
评论(0)