Java多线程面试重点-1

news2025/2/24 7:01:01

0. 什么是并发?什么是并行?

  • 并发:把时间分成一段一段,每个线程轮流抢占时间段。 如果时间段非常短,线程切换非常快,被称为伪并行。
  • 并行:多个线程可以同时运行。

并发与并行造成的影响?

多线程问题:线程安全,死锁等

1. 如何预防死锁?

先说明死锁发生的四个必要条件:

  • 互斥条件:同一时间只能有一个线程获取资源(因为资源有限)。
  • 不可剥夺条件:一个线程已经占有的资源,在释放之前不会被其它线程抢占。(@&@20230130)
  • 请求和保持条件:线程等待过程中不会释放已占有的资源。
  • 循环等待条件:多个线程互相等待对方释放资源。

死锁预防,破坏这四个必要条件:

  • 由于资源互斥是资源使用的固有特性,无法改变,我们不讨论
  • 破坏不可剥夺条件:
    • 一个进程不能获得所需要的全部资源时就进入等待状态,此时释放调自己持有的资源,让其它进程使用。再等待结束时,重新获取原有资源。
  • 破坏请求和持条件:
    • 方法一:静态分配,即每个进程在开始执行时就申请它所需要的全部资源。
    • 方法二:动态分配,即每个进程在申请所需要的资源时,它本身不占用系统资源。
  • 破坏循环等待条件:
    • 采用资源有序分配,将系统中的所有资源顺序编号,将紧缺的,稀少的采用较大的编号,在申请资源时必须按照编号的顺序进行,一个进程只有获得较小编号的进程才能申请较大编号的进程。

2. 多线程有哪几种创建方式?

  • extend Thread Override run()
  • implement Runnable Override run() and new Tread(Runnable r)
  • implement Callable Override call() and FutureTask
  • ThreadPool
  • new Tread(lambda).start()

3. 描述一下线程安全活跃态问题,竞态条件?(@&@)

活跃性问题可以分为:死锁、活锁、饥饿

活锁:**

  • 概念:线程没有被阻塞,由于某些条件没有满足,导致一直重复尝试。
  • 场景1:异步的消息队列就有可能造成活锁。在消息队列的消费端,如果没有正确的ack消息,并且执行过程中报错了,就会再次放回到消息头,然后再拿出来执行,一直循环往复的失败。这个问题除了正确的ack之外,往往是通过将失败的消息放入到延时队列中,等到一定的延时再进行重试来解决。
  • 场景2:递归没有写退出条件。
  • 解决:尝试等待一个随机的时间就可以,会按时间轮去重试。

饥饿:**

  • 概念:线程因无法访问所需资源,而无法执行下去的情况。
  • 两种情况:
    • 线程在临界区做了无限循环或无限制等待资源的操作,让其它的线程一直不能拿到锁进入临界区,对其它线程来说,就进入了饥饿状态。(现在理解了20230130)
    • 线程优先级不合理的分配,导致部分线程始终无法获取到CPU资源,而一直无法执行。
  • 场景:读写锁,一直在读,写锁一直等待。
  • 解决:
    • 保证资源充足,很多场景下,资源的稀缺性无法解决。
    • 公平分配资源,在并发编程里使用公平锁,例如FIFO策略,线程等待是有顺序的,排在等待队列前面的线程会优先获得资源。
    • 避免持有锁的线程长时间执行,很多场景下,持有锁的线程的执行时间也很难缩短。

死锁:

  • 概念:线程在对同一把锁进行竞争时,未抢占到锁的线程会等待持有锁的线程释放锁后继续抢占,如果两个或两个以上的线程互相持有对方将要抢占的锁,互相等待对方先行释放锁就会进入到一个循环等待的过程,这个过程就叫做死锁。

竞态条件:**

  • 概念:
    • 同一个程序的多线程访问同一个资源,如果对资源的访问顺序敏感,就称存在竞态条件。
    • 代码区成为临界区。
    • 与大多数并发错误一样,竞态条件不总是会产生问题,还需要不恰当的执行时序。
  • 最常见的竞态条件:
    • 先检测后执行的操作,执行依赖于检测结果,而检测结果依赖于多个线程的执行时序,多个线程的执行时序通常情况下是不固定不可判断的,从而导致执行结果出现各种的问题。一种可能的解决办法就是:在一个线程修改访问一个状态时,要防止其他线程访问修改,也就是加锁机制,保证原子性。
    • 延迟初始化(典型的赖汉单例)

4. 描述一下进程与线程区别?

进程(Process)是系统进行资源分配和调度(管理)的基本单位,进程是资源分配的最小单位,是程序一次动态执行的过程。

线程:是执行的最小单位,一般不具有资源。线程是由进程产生的。

5. 描述一下Java线程的生命周期?

总:

Java线程的生命周期有5种状态,分别是:新建、就绪、运行、阻塞和销毁。在Linux底层的线程只有:运行、阻塞和销毁。

Java线程的生命周期:

  • 新建:new出来的线程。
  • 就绪:调用线程的start()后,线程处于等待CPU分配资源的阶段,谁先抢到CPU资源,谁开始执行。
  • 运行:当就绪的线程被调度,并获得CPU资源时,便进入运行状态,run()定义了线程的操作和功能。
  • 阻塞:线程调用 sleep()、wait()就处于了阻塞状态,处于阻塞状态的线程需要调用某种机制唤醒,比如调用notify()、notifyAll()。唤醒的线程不会立刻执行run(),它们要再次等待CPU分配资源进入运行状态。
  • 销毁:线程正常执行完毕后、线程被提前强制性的终止、出现异常导致结束,那么线程就要被销毁,释放资源。

Linux底层线程三种状态:**

运行、阻塞、销毁。JVM是虚拟出来的一套操作系统,在创建Thread对象时,还没有调用Linux的线程,所以新增了一个新建状态。调用Thread.start()时,调用Linux的线程,但是不能立即执行,需要等待CPU分配资源,所以有了就绪状态。

JDK的源码的Thread状态(6种):

  • NEW:尚未启动的线程的线程状态
  • RUNNABLE:处于可运行状态的线程,它正在JVM中执行,但它可能正在等待来自操作系统(例如处理器)的其他资源。它有细分READY (准备状态)和RUNNING (可运行状态)。
  • BLOCKED:被阻塞,正在等待着锁。
  • WAITING: 等待被唤醒。例如:在对象上调用Object.wait()的线程等待另一个线程调用Object.notify()或Object.notifyAll();调用Thread.join()的线程正在等待指定的线程终止。
  • TIMED_WAITING : 具有指定等待时间的等待线程的线程状态。使用如下:
    • Thread.sleep(long)
    • Object.wait(long)
    • Thread.join(long)
    • LockSupport.parkNanos(long...)
    • LockSupport.parkUntil(long...)
  • TERMINATED:线程已完成执行。

6. 线程池设置多少线程数合适?

首先确认业务是CPU密集型还是IO密集型的,根据不同情况去判断。

CPU密集型程序:

  • 特点:I/O操作时间短, CPU运算处理多。
  • 单核CPU:处理CPU密集型程序,不太适合多线程。
  • 多核 CPU:处理CPU密集型程序,最大化的利用CPU核心数,应用并发编程来提高效率。
    • 理论上:线程数量 = CPU 核数(逻辑)
    • 实际上:线程数量 = CPU 核数(逻辑)+ 1(经验值)
      • 如果恰好某一个线程出问题而暂停,刚好有一个“额外”的线程,可以确保在这种情况下CPU周期不会中断工作。

I/O 密集型程序:

  • 特点: I/O 操作占比很大部分,等待时间较长。线程等待时间所占比例越高,需要越多线程。
  • 公式:CPU 核数 / (1 - 阻塞系数);阻塞系数 在 0.8 ~ 0.9 之间。
  • 一般是:线程数量 = 2*CPU核数 + 1
  • 实际上:在2N+1上,进行压测逐步添加

实际情况看压测:

看系统负载:-> Linux使用uptime命令 -> 系统负载与CPU核心数量有关,理想情况下,一个核心被一个进程占用。如果4个核心,跑4个进程,此时Load是4但是也不高。

7. wait()和sleep()的区别与联系?

区别:

  • 所属类:wait()是Object的方法,sleep()是Thread的方法(拓展一下为什么在Object、Thread中)。
  • 作用范围:sleep没有释放锁,只是休眠,而wait释放了锁后等待,使得其他线程可以使用同步控制块或方法。
  • 使用范围: wait、notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。
  • 异常范围:sleep必须捕获异常,而wait,notify和notifyAll不需要强制地捕获异常。

联系:

sleep、wait调用后都会暂停当前线程并让出CPU的执行时间,并且都能被唤起。

8. 描述一下notify()和notifyAll()区别?

  • notifyAll():唤醒所有,notify():随机唤醒一个。
  • 使用流程:
    • 线程调用了对象的wait(),线程进入该对象的等待池中,等待池中的线程,不会去竞争该对象的锁。
    • 如果其它线程调用了对象的notifyAll()或notify(),被唤醒的的线程便会进入该对象的锁池中,锁池中的线程会去竞争该对象锁。竞争成功则继续执行。

拓展:"锁池"和"等待池"的概念:

  • 锁池:线程A已经拥有了某个对象(不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(块),但是该对象的锁现在正被线程A拥有,这些其他线程就进入了该对象的锁池中。
  • 等待池:
    • 线程A调用了某个对象的wait(),线程A就会释放该对象的锁(因为wait()必须在synchronized中,在执行wait()之前,线程A就已经拥有该对象的锁),同时该线程A进入到该对象的等待池中。
    • 如果另外的一个线程调用了相同对象的notifyAll(),处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。
    • 如果另外的一个线程调用了相同对象的notify(),仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池。

9. 描述一下synchronized和lock区别 ?

  • 层次:Lock是一个接口,底层使用AQS框架实现;Synch是关键字,底层通过JVM实现的(monitor对象和对象头Mark Word)。
  • 锁的获取:Lock可以使用tryLock判断有没有锁。
  • 锁的释放:Lock需要在finally中自己释放,发生异常时,如果没有主动去释放锁,会导致死锁;Synch会自动释放,发生异常时,不会死锁。
  • 响应中断:Lock等待锁过程中可以用interrupt来中断等待,而Synch只能等待锁的释放,不能响应中断。
  • 锁的状态:Lock可以通过trylock()知道有没有获取锁,而Synch不能。
  • 公平锁:Lock可以设置为公平锁与非公平锁,而Synch只能是非公平锁。
  • 性能:Lock大量同步,Synch少量同步。Lock可以提高多个线程进行读操作的效率。(可以通过ReadWriteLock实现读写分离)

对象头:(主要背一下锁标志位)

拓展Synch的加锁流程:***** 

  • HotSpot研究发现,大多数情况下,锁总是由同一线程多次获得,引入了偏向锁。
  • 偏向锁在JDK1.6以上默认开启,开启后程序启动几秒后才会被激活。
  • 装逼点(不要瞎BB):批量重偏向与批量撤销

https://blog.csdn.net/u022812849/article/details/108531031

  • 获取偏向锁流程:
    • I. 判断是否为可偏向状态:MarkWord中锁标志是否为‘01’,是否偏向锁是否为‘1’。
    • II. 如果是可偏向状态,则查看MarkWord中线程ID是否为当前线程,如果是,则进入步骤 V,否则进入步骤III。
    • III. 通过CAS操作竞争锁,如果竞争成功,则将MarkWord中线程ID设置为当前线程ID,然后执行V;竞争失败,则执行IV。
    • IV. CAS获取偏向锁失败表示有竞争。当达到safepoint时获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码块。
    • V. 执行同步代码。
  • 轻量级锁是自旋锁,减少CPU上下文的切换,在线程交替执行同步块时,会提高性能。
  • 轻量级锁获取过程:
    • I. 进行加锁操作时,如果没有创建锁记录(Lock Record),则会在当前线程栈帧中划出一块空间,作为该锁的锁记录,并且将锁对象MarkWord复制到该锁记录中(偏向锁的时候也会生成)。
    • II. 复制成功之后,JVM使用CAS操作将对象头的MarkWord更新为指向当前线程的锁记录指针,并将锁记录里的Owner指针指向对象头的MarkWord。如果成功,则执行III,否则执行IV
    • III. 更新成功,则当前线程持有该对象锁,并且对象MarkWord锁标志设置为‘00’,即表示此对象处于轻量级锁状态。
    • (IV. 更新失败,JVM先检查对象MarkWord是否指向当前线程栈帧中的锁记录,如果是则执行V,否则执行VI。
    • V. 表示锁重入;然后当前线程栈帧中增加一个锁记录:第一部分(Displaced Mark Word)为null,并指向Mark Word的锁对象,起到一个重入计数器的作用。)
    • VI. 表示该锁对象已经被其他线程抢占,则进行自旋等待(默认10次),等待次数达到阈值仍未获取到锁,则升级为重量级锁。
  • 当有多个锁竞争轻量级锁则会升级为重量级锁,重量级锁正常会进入一个CXQ队列(竞争队列),有资格成为候选资源的线程进入EntryList,通过竞争获取锁资源(成为Owner)。在调用wait()之后,则会进入一个waitSet队列park等待,而当调用notify()唤醒之后,则有可能进入EntryList(看图,背图)。

  • 重量级锁是依赖对象内部的monitor锁来实现的,而monitor又依赖操作系统的MutexLock(互斥锁)来实现的。
  • 重量级锁加锁过程:
    • I . 分配一个ObjectMonitor对象,把Mark Word锁标志置为10,然后MarkWord存储指向ObjectMonitor对象的指针。每个需要获取锁的线程都包装成ObjectWaiter对象。
    • II . 多个线程同时执行同一段同步代码时,ObjectWaiter先进入EntryList队列,当某个线程获取到对象的monitor以后进入Owner区域,并把monitor中的owner变量设置为当前线程同时monitor中的计数器count+1;

10. 简单描述一下ABA问题?

ABA过程:

  • 有两个线程同时去修改一个变量的值,比如线程1和线程2,都将变量值从A更新成B。
  • 首先线程1获取到CPU的时间片,线程2发生阻了塞进行等待,线程1通过CAS把值从A更新成B。
  • 线程1更新完后,恰好有线程3想要把变量的值从B更新成A。
  • 线程3更新成功后,线程2获取到CPU的时间片,进行CAS,发现值是预期的A,然后有更新成了B。
  • 但是线程1并不知道,该值已经有了A->B->A这个过程,这也就是我们常说的ABA问题。

解决:

可以通过加版本号或者加时间戳解决,或者保证单向递增或者递减就不会存在此类问题。Java中也有相关引用原子类。

11. 实现一下DCL(双重检测)?

用单例的方式说明DCL,加锁前后都判断对象是否为空。为了解决并发可能导致实例两个对象。自己代码中也用到过。(凤凰、神州租车用到过)

拓展点:DCL单例需要使用volatile关键字,防止指令重排序的优化,导致拿到半初始化的对象。

具体代码如下:

public class Singleton {
    // volatile是防止指令重排
    private static volatile Singleton singleton;
    private Singleton() {}
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Signletion();
                } 
           }
       }
       return singleton;
   }
} 

12. 实现一个阻塞队列?

三种方法:

  • 使用Synchronized中wait() + notify()
  • 使用Lock中Condition的await() + signal()
  • 使用ArrayBlockingQueue队列的put() + take()

具体见代码:

《springboot-multi-thread》 com.hanxiaozhang.threadbase1ndedition.no98producerandconsumer

13.实现多个线程顺序打印abc?

public class PrintABC {
    ReentrantLock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();
    Condition conditionC = lock.newCondition();
    volatile int value = 0;
    
    public void printABC() {
        new Thread(new ThreadA()).start();
        new Thread(new ThreadB()).start();
        new Thread(new ThreadC()).start();
    } 
    
    class ThreadA implements Runnable{
        @Override
        public void run() {
            lock.lock();
            try {
                while (value % 3 != 0) {
                    conditionA.await();
                } 
                System.out.print("A");
                conditionB.signal();
                value ++;
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
    ... ... 

14.多线程之间是如何通信的?

  • 通过共享变量,变量需要volatile修饰。
  • 使用wait()和notifyAll(),但是由于需要使用同一把锁,所以必须通知线程释放锁,被通知线程才能获取到锁,这样导致通知不及时。
  • 使用Condition的await()和signalAll()方法。
  • 使用CountDownLatch实现,通知线程到指定条件,调用cdl.countDown(),被通知线程进行cdl.await()。

15.描述一下Synchronized底层实现,以及和Lock的区别?

对像头可以说明锁的四种状态:

结合第9题开始说。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1821035.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s之kubelet证书时间过期升级

1.查看当前证书时间 # kubeadm alpha certs renew kubelet Kubeadm experimental sub-commands kubeadm是一个用于引导Kubernetes集群的工具,它提供了许多命令和子命令来管理集群的一生周期。过去,某些功能被标记为实验性的,并通过kubeadm a…

vue3 前端验证码-删除最后一个,焦点聚焦在前一个值上,并不会删除值

删除最后一个数字&#xff0c;焦点聚焦在前一个值上&#xff0c;并不会删除值 <inputv-for"(box, index) in boxes":key"index"ref"inputRefs":value"box"input"onInputChange(index)"keyup"onKeyDown($event, inde…

WARNING: pip is configured with locations that require TLS/SSL

在pycharm中运行pip下载软件包遇到该问题&#xff1a;WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available 原因&#xff1a;没有安装openssl&#xff1b; 到https://slproweb.com/products/Win32OpenSSL.ht…

u-boot(五) - 启动流程概述

一&#xff0c;XIP设备 一上电&#xff0c;CPU必定从XIP设备得到第1条指令。 XIP设备是指一种可以直接在存储器中执行程序代码的设备&#xff0c;而不需要将代码复制到内存中。XIP的全称是eXecute In Place&#xff0c;即芯片内执行。这类设备包括片内的SRAM、NOR Flash、Boot…

社区论坛圈子软件APP ,提供互动交流、知识共享和专业交流的社交平台。

社区论坛圈子软件APP的开发能够为用户提供一个互动交流的社交平台&#xff0c;促进用户之间的知识分享、交流和互助。本文将突出社区论坛圈子软件APP的前景、作用和特点&#xff0c;以帮助您了解该系统的潜力和优势。 一、前景&#xff1a; 知识共享&#xff1a;社区论坛圈子软…

线程有规律循环打印输出,线程拷贝图片运用

1&#xff1a;线程打印循环&#xff08;保证循环顺序输出&#xff09; 使用互斥锁和条件变量实现&#xff1a; #include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <semaphore.h>…

【SAP-ABAP】-权限批导-批量给某个角色导入事务码权限

需求&#xff1a;SAP期初上线的时候&#xff0c;业务顾问经常会遇到批量创建角色和分配角色权限的情况 岗位需求&#xff1a;一般是业务顾问定义权限&#xff0c;BASIS进行后期运维&#xff0c;今天讲两个批导功能&#xff0c;方便期初上线 主要函数&#xff1a;PRGN_READ_ROLE…

群体优化算法----多乌鸦搜寻算法介绍,找多目标函数组解,Pareto前沿

介绍 乌鸦搜寻算法&#xff08;Crow Search Algorithm&#xff0c;CSA&#xff09;是一种新型的群体智能优化算法&#xff0c;其灵感来源于乌鸦的行为特性&#xff0c;尤其是乌鸦在食物搜寻和藏匿过程中的智能行为。乌鸦是一种高度聪明的鸟类&#xff0c;它们展示出复杂的社会…

html实现粘贴excel数据,在页面表格中复制

录入数据时&#xff0c;有时候需要把excel中的数据一条条粘贴到页面中&#xff0c;当数据量过多时&#xff0c;这种操作很令人崩溃。本篇文章实现了从excel复制好多行数据后,可在页面粘贴的功能 具体实现代码 <!DOCTYPE html> <html lang"en"> <head…

自适应巡航控制技术规范(简化版)

自适应巡航控制技术规范(简化版) 1 系统概述2 功能需求3 性能需求4 功能激活条件5 功能抑制条件6 系统局限性1 系统概述 ACC 自适应巡航系统可自动控制纵向跟车距离,减轻驾驶员的工作量,即驾驶员无需频繁的踩制动和油门便可完成部分的驾驶任务,但责任主体仍然是驾驶员,驾…

OrangePi AIpro测评:性能、应用与开发者体验解析

一、OrangePi AIpro介绍 OrangePi AIpro(8T)采用昇腾AI技术路线&#xff0c;具体为4核64位处理器AI处理器&#xff0c;集成图形处理器&#xff0c;支持8TOPS AI算力&#xff0c;拥有8GB/16GB LPDDR4X&#xff0c;可以外接32GB/64GB/128GB/256GB eMMC模块&#xff0c;支持双4K高…

SPI转四串口芯片CH9434的设计

一、CH9434的介绍 CH9434 是一款SPI转四串口转接芯片&#xff0c;提供四组全双工的9线异步串口&#xff0c;用于单片机/嵌入式系统扩展异步串口。CH9434包含四个兼容16C550的异步串口&#xff0c;最高支持4Mbps波特率通讯。最多支持25 路GPIO&#xff0c;提供半双工收发自动切换…

Rust基础学习-ModulesPackage

在Rust中&#xff0c;模块有助于将程序分割成逻辑单元&#xff0c;以提高可读性和组织性。一旦程序变得更大&#xff0c;将其拆分为多个文件或命名空间非常重要。 模块有助于构建我们的程序。模块是项目的集合&#xff1a;包括函数、结构体甚至其他模块。 Module 定义模块 在…

嵌入式硬件VS软件,到底哪个更难?

在嵌入式系统开发中&#xff0c;硬件和软件是密不可分的两个方面。但是&#xff0c;究竟是硬件开发更具挑战性&#xff0c;还是软件开发更难以应对呢&#xff1f;本文将就这一问题展开讨论&#xff0c;探究嵌入式硬件和软件在开发过程中的各种挑战与特点。 一、硬件开发&#…

12.实战私有数据微调ChatGLM3

实战私有数据微调ChatGLM3 实战私有数据微调ChatGLM3实战构造私有的微调数据集基于 ChatGPT 设计生成训练数据的 Prompt使用 LangChain GPT-3.5-Turbo 生成训练数据样例训练数据解析、数据增强和持久化存储自动化批量生成训练数据集流水线提示工程&#xff08;Prompt Engineer…

HTTPS请求阶段图解分析

HTTPS请求阶段分析 请求阶段分析 请求阶段分析 一个完整、无任何缓存、未复用连接的 HTTPS 请求需要经过以下几个阶段&#xff1a; DNS 域名解析、TCP 握手、SSL 握手、服务器处理、内容传输。 一个 HTTPS 请求共需要 5 个 RTT 1 RTT&#xff08;域名解析&#xff09; 1 RTT…

element table 点击某一行中按钮加载

在Element UI中&#xff0c;实现表格&#xff08;element-table&#xff09;中的这种功能通常涉及到数据处理和状态管理。当你点击某一行的按钮时&#xff0c;其他行的按钮需要动态地切换为加载状态&#xff0c;这可以通过以下步骤实现&#xff1a; 1.表格组件&#xff1a;使用…

NodeClub:NodeJS构造开源交流社区

NodeClub&#xff1a; 连接每一个想法&#xff0c;NodeClub让社区更生动- 精选真开源&#xff0c;释放新价值。 概览 NodeClub是一个基于Node.js和MongoDB构建的社区系统&#xff0c;专为开发者和社区爱好者设计。它提供了一套完整的社区功能&#xff0c;包括用户管理、内容发…

基于 Nginx Ingress + 云效 AppStack 实现灰度发布

作者&#xff1a;子丑 场景简介 灰度发布是降低生产部署风险&#xff0c;提升线上服务稳定性的重要手段&#xff0c;这在当前快速迭代的软件研发中尤为重要。相对于 K8s 默认的滚动部署或者简单的 Pod 分批&#xff0c;基于流量特征的灰度发布验证更精准&#xff0c;风险更低…

安鸾学院靶场——安全基础

文章目录 1、Burp抓包2、指纹识别3、压缩包解密4、Nginx整数溢出漏洞5、PHP代码基础6、linux基础命令7、Mysql数据库基础8、目录扫描9、端口扫描10、docker容器基础11、文件类型 1、Burp抓包 抓取http://47.100.220.113:8007/的返回包&#xff0c;可以拿到包含flag的txt文件。…