JAVA 并发真讨厌

举报
赵KK日常技术记录 发表于 2023/06/24 13:51:52 2023/06/24
【摘要】 互联网行业随着商业化,信息化,快速发展至今,借助人口大国和时代催生,早已到了秀才不出门便知天下事的年代,80后吃饭就着菜,90后吃饭就着肉,00后吃饭就着paid,多媒体,小视频,流量明星,随着5G的普及,互联网将跨入新时代。 人口多,那么带给互联网就少不了高并发,什么叫高并发?单位时间内处理的请求量叫做高并发。高并发就离不开多线程操作。 既然是高并发,就对应了JUC包的API...

互联网行业随着商业化,信息化,快速发展至今,借助人口大国和时代催生,早已到了秀才不出门便知天下事的年代,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劝退师,好东西需要分享,干货满满

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。