java 线程之间通信-volatile 和 synchronized
你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益:
- 了解大厂经验
- 拥有和大厂相匹配的技术等
希望看什么,评论或者私信告诉我!
文章目录
- 一、背景
- 二、线程之间通信的基本储备
- 2.1 为什么线程之间需要通信
- 2.2 现代处理器结构
- 2.3 基于现代处理器结构下的线程运行模型
- 2.4 线程工作内存带来的问题
- 三、volatile 和 synchronized
- 3.1 volatile是什么
- 3.1.1 可见性
- 3.1.2 禁止指令重排序优化
- 3.1.3 内存屏障(Memory Barrier)
- 3.1.4 不保证原子性
- 3.1.5 使用场景
- 3.2 volatile 原理和例子
- 3.2 synchronized 是什么
- 3.2.1. 基本用法
- 3.2.1.1 同步方法
- 3.2.1.2 同步代码块
- 3.2.2. 工作原理
- 3.2.3. 保证原子性和可见性
- 3.3 synchronized 原理和例子
- 四、总结
一、背景
前面两篇,我们分别知道了 关于 java 多线程,你需要知道的一些基础知识 以及 关于 java 多线程,你需要知道的一些基础知识
本篇文章呢,我们继续死磕 java 多线程,来聊一聊 java 多线程之间是如何通信的-volatile 和 synchronized
二、线程之间通信的基本储备
2.1 为什么线程之间需要通信
在线程编程中,线程之间需要相互通信的主要原因是协作和数据共享。以下是一些主要的原因:
-
资源共享: 多个线程可能需要同时访问和操作共享的资源,如数据结构、文件、网络连接等。为了避免数据竞争和确保数据的一致性,线程之间需要通信来协调对共享资源的访问。
-
任务分工: 在多线程编程中,不同线程可以负责不同的任务或子任务,线程之间需要协作和通信以完成整体的工作。通信可以是单向的传达结果,也可以是双向的交换信息和状态。
-
同步操作: 线程之间的通信可以用于同步操作,例如一个线程需要等待另一个线程完成某个任务后才能继续执行,或者通知其他线程某个事件已发生。
-
数据传递: 线程之间通过通信来传递数据和消息,以便于协调工作、共享信息或通知事件。
-
提高性能: 在某些情况下,通过线程之间的通信和协作可以提高程序的性能,例如使用线程池执行并发任务时,可以减少线程的创建和销毁开销。
-
实现某些模型和算法: 有些并发模型和算法需要线程之间的协作和通信,如生产者消费者模型、并发队列等。
综上所述,线程之间的通信在多线程编程中是非常重要的,能够实现不同线程之间的协作、数据共享、任务分工等功能,从而有效利用计算资源并实现复杂的并发任务。
2.2 现代处理器结构
一般情况下,现代处理器通常会包含一级缓存(L1 Cache)、二级缓存(L2 Cache)、和三级缓存(L3 Cache)。这些缓存一般都是集成在处理器芯片内部的,被称为“内置缓存”(On-Chip Cache),用于加快数据的访问速度和减少对主内存的访问。这里有一个 2020年的数据
L1 cache 访问时间是 1ns
L2 cache 访问时间是 4ns
主存访问时间是 100ns
具体关于三级缓存(L3 Cache)通常的情况包括:
- 位置: L3 Cache通常位于处理器芯片内部,但是相对于L1和L2 Cache,它的容量更大,从几MB到几十MB不等。
- 作用: L3 Cache主要用来缓存多个核心之间共享的数据,以提高处理器核心之间的数据共享效率。
- 互相之间是否独立: 不同处理器核心之间可以访问共享的L3 Cache,这有助于提高多个核心之间数据访问的效率。
由于L3 Cache容量较大且能够为多个核心提供共享数据缓存,因此它可以有效地提高多核处理器系统中核心之间的数据共享和协作效率。虽然L3 Cache通常也集成在处理器芯片内部,但某些处理器架构可能会将部分L3 Cache放置在处理器芯片外部以适应不同的需求。
当系统运行时,CPU执行计算的过程如下:
- 程序以及数据被加载到主内存
- 指令和数据被加载到CPU缓存
- CPU执行指令,把结果写到高速缓存
- 高速缓存中的数据写回主内存
2.3 基于现代处理器结构下的线程运行模型
线程的工作内存其实就是多级缓存以及CPU寄存器的抽象。
所以每个线程在运行时确实都会有自己的一套完整的上下文,这个上下文包含了线程当前的状态、执行环境以及必要的数据。这个上下文在线程切换时被保存和恢复,以确保线程可以从中断点继续执行。下面是上下文的一些重要组成部分:
-
寄存器状态: 在上下文中,包含了线程当前寄存器的状态。寄存器存储了当前线程的执行环境,包括程序计数器、栈指针、各种通用寄存器等。
-
栈: 程序使用的栈包含了函数调用、局部变量以及其他执行环境的信息。每个线程都有自己的栈,用于存储执行过程中的临时数据。
-
程序计数器(Program Counter): 程序计数器存储着当前执行的指令地址或者是下一条待执行的指令地址。
-
线程状态: 这部分描述了线程当前所处的状态,比如运行态、就绪态、阻塞态等。线程状态的改变会触发线程调度。
-
权限和访问控制: 上下文中可能包含了线程的权限信息,以确保线程的操作在合适的权限下进行。
-
堆栈指针信息: 记录了当前线程堆栈的指针位置,在进行栈操作时起着重要作用。
-
资源分配信息: 上下文还可能包括了线程已获得的资源、线程使用的栈大小等信息。
通过保存和恢复这些上下文信息,操作系统能够有效地管理多个线程的执行,实现线程之间的切换和并发执行。这些上下文信息是确保线程能够在不同执行环境下正确运行的关键。
2.4 线程工作内存带来的问题
线程有自己的工作内存最大的问题之一就是数据不一致性问题。这种情况可以导致程序出现难以预测的错误行为,因为多个线程可能会在各自的工作内存中缓存共享变量的副本,而这些副本的更新可能无法即时反映到其他线程中,引发数据的不一致性。
数据不一致性问题的一些常见情形包括:
-
写问题(Write Problem): 一个线程在自己的工作内存中修改了共享变量但未立即写回主内存,导致其他线程无法立即看到这个变化。
-
读问题(Read Problem): 一个线程从主内存中读取了共享变量的值,但由于另一个线程已经对该变量进行了修改,该线程的工作内存中的值已经过时,导致读取的值不正确。
-
指令重排序问题: 编译器或处理器可能会对指令进行重排序优化,这可能导致线程在不同的顺序下访问共享变量,进而使得数据出现不一致的情况。
其实就是两类问题:
- 数据可见性的问题,即另外一个线程改了共享变量,我能不能马上知道。
- 共享变量一致性的问题,即多个线程操作同一个共享变量,它的结果能不能跟非多线程操作同一个共享变量的结果一致。
为了解决上述的两个问题,我们引入了 volatile 和 synchronized
三、volatile 和 synchronized
3.1 volatile是什么
volatile
是 Java 中的一个关键字,主要用于确保多线程环境下变量的可见性和有序性。当一个变量被声明为 volatile
时,意味着这个变量可能会被多个线程同时访问和修改,因此需要使用 volatile
来确保所有线程都能看到变量的最新值。
下面是 volatile
的详细解释:
3.1.1 可见性
在多线程环境中,一个线程修改了一个共享变量的值,另一个线程无法立即看到这个变化,除非它主动读取该变量的值。而 volatile
关键字保证了当一个线程修改了一个 volatile
变量的值后,其他线程会立即看到这个变化。这是因为 volatile
变量不会被缓存到线程的工作内存中,每次读取 volatile
变量时都会直接从主内存中获取最新值。
3.1.2 禁止指令重排序优化
编译器和处理器可能会对代码进行指令重排序优化,以提高执行效率。但是,在某些情况下,这种重排序可能会导致多线程环境下的数据不一致问题。volatile
关键字可以防止这种情况发生,它会告诉编译器和处理器不要对这个变量进行重排序优化。
3.1.3 内存屏障(Memory Barrier)
现代处理器为了提高性能会对内存操作进行优化,包括重新排序读写操作。为了强制处理器的操作符合程序员的预期顺序,编译器会在使用volatile的读/写操作周围插入内存屏障(Memory Barrier)。这些内存屏障是一种同步机制,用于阻止屏障两侧的指令被重排序。通过确保特定的读写操作顺序执行,内存屏障确保了程序中的某些操作在特定时刻已经执行完成或已经启动执行,从而在多线程环境中维持操作的有序性。
3.1.4 不保证原子性
虽然 volatile
可以保证可见性和禁止指令重排序优化,但它不能保证复合操作(如自增或自减等)的原子性。如果需要一个变量在多线程环境下的原子性操作,如计数或状态更新等,应该使用 AtomicInteger
或 AtomicLong
等原子类或者使用 synchronized
块来保证原子性。但对于简单的状态标记(例如一个标志位),volatile
是足够的。
3.1.5 使用场景
volatile
主要用于以下场景:
- 状态标记:例如用于标记某个任务是否已经完成。在这种情况下,一个线程会检查这个标记,然后基于这个标记的值来决定下一步行动。如果这个标记在多线程环境下被使用,并且可能被多个线程同时修改,那么就需要使用
volatile
来确保每个线程都能看到最新的标记值。 - 单例模式的双重检查锁定:在某些单例模式的实现中,会使用
volatile
来确保实例在多个线程间的正确创建和访问。
总的来说,volatile
是一个轻量级的同步机制,用于确保多线程环境下变量的可见性和有序性。但在需要复杂同步操作或原子性保证的情况下,可能需要考虑使用更强大的同步机制,如 synchronized
块或锁。
3.2 volatile 原理和例子
volatile 状态标记 的例子:
public class StopThreadExample {// 使用volatile修饰的变量来确保所有线程都能看到最新的标志位值private volatile boolean flag= true;// 一个任务执行线程,它持续检查标志位并根据标志位决定是否继续运行public void runTask() {while (isRunning) { // 使用volatile修饰的变量确保我们能正确读取到最新的状态// 这里模拟一些耗时任务System.out.println("执行任务...");try {Thread.sleep(1000); // 模拟耗时操作,这里暂停一秒} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("任务执行线程已经停止.");}public static void main(String[] args) throws InterruptedException {StopThreadExample example = new StopThreadExample();Thread taskThread = new Thread(() -> example.runTask()); // 启动任务执行线程taskThread.start(); // 开始执行任务线程try {TimeUnit.SECONDS.sleep(5);} catch (InterruptedException e) {e.printStackTrace();}; // 让主线程暂停几秒以便观察效果,模拟主线程正在做其他事情的情况System.out.println("停止任务执行线程..."); // 在主线程中通知任务执行线程停止执行example.flag= false; // 设置标志位来停止任务执行线程,所有线程都会看到最新的标志位值,因为使用了volatile关键字修饰isRunning变量taskThread.join(); // 确保任务执行线程停止后主线程继续执行接下来的代码或结束程序(这一步依赖于主线程的下一步动作)System.out.println("主线程结束."); // 当任务执行线程已经停止后,主线程结束程序或继续其他操作(这里模拟主线程的下一步动作)}
}
在字节码层面 volatile 原理,是通过 flags 表示来实现的
3.2 synchronized 是什么
synchronized
是 Java 中用于控制多线程并发访问共享资源的一种关键字。它可以确保多个线程在同一时刻只能有一个线程执行某个代码块或方法,从而避免并发问题,如竞态条件。以下是关于 synchronized
的详细介绍:
3.2.1. 基本用法
3.2.1.1 同步方法
直接在方法声明上使用 synchronized
关键字,这样整个方法都在同步块内。例如:
public synchronized void synchronizedMethod() {// 同步代码块
}
此时,该方法只能由一个线程在任何时候访问。多个线程调用此方法时,其他线程会被阻塞直到当前线程执行完毕。这种方法的同步锁是当前实例对象(即 this
)。如果要同步的是静态方法,锁是类的 Class
对象。
3.2.1.2 同步代码块
可以使用 synchronized(锁对象)
语法创建一个同步代码块。例如:
synchronized (lockObject) {// 同步代码块内容
}
此时,只有持有锁对象的线程可以进入该代码块。多个线程可以尝试访问这个同步块,但只有一个能获得锁并执行其中的代码。其他线程会被阻塞直到锁被释放。锁对象可以是任何对象,通常是一个自然存在的共享资源或者一个特定的锁对象。当锁对象是 this
时,相当于同步整个方法。如果锁对象是某个静态变量,那么任何线程调用这段代码都需要获得那个锁才能执行。但一定要确保使用的锁对象不会在方法中频繁变化。如果对象在不同的上下文中表示不同的资源或意义,则可能导致意外的并发问题。
3.2.2. 工作原理
当一个线程进入一个 synchronized
代码块或方法时,它首先尝试获取锁对象对应的内置锁(也称为监视器锁)。如果锁已经被另一个线程持有,那么该线程将会进入等待状态,直到锁被释放(由持有锁的线程退出同步块或调用 wait()
方法)。这种机制确保了同一时刻只有一个线程可以访问同步代码块或方法中的共享资源。一旦线程释放锁(退出同步块或方法),其他等待的线程将有机会尝试获取该锁并执行相应的代码。如果多个线程同时尝试获取同一个对象的锁,它们会被按照某种顺序来串行化地执行同步代码块或方法。值得注意的是,同步控制开销通常比上下文切换的开销要小得多。此外,JVM 会尝试优化锁的获取和释放过程以提高性能。对于复杂的应用场景,还有专门的性能调优和死锁避免策略可用。
3.2.3. 保证原子性和可见性
是的,我的解释是正确的。在 Java 中使用 synchronized
关键字时,确实涉及到内存模型和工作内存与主内存的刷新问题,特别是在多线程环境下。让我们再次详细解释这一点。
当你在 Java 程序中使用 synchronized
块时,这个关键字确保了多个线程对共享资源的同步访问。这是通过确保只有一个线程能够获取到锁来实现的。在这个同步块内,所有的读写操作都是对该锁对象的原子操作。这就意味着当一个线程进入 synchronized
块时,它会获取锁对象,并开始执行同步块内的代码。此时,其他尝试进入该同步块的线程会被阻塞,直到持有锁的线程释放锁为止。
在这个过程中,涉及到内存模型和工作内存与主内存的交互:
- 互斥访问:当一个线程进入 synchronized 块时,它需要获得锁。只有获得锁的线程才能执行同步块内的代码,从而保证了同一时刻只有一个线程在操作共享变量。
- 工作内存与主内存的刷新:当一个线程持有锁并执行同步块内的操作时,它会首先从主内存中读取共享资源到工作内存中(即线程的本地缓存)。在工作内存中修改这些数据后,只有当线程释放锁并允许其他线程获取锁时,这些修改才会被写回主内存。这就意味着同步块内的操作保证了在工作内存中对共享数据的操作在所有线程之间是一致的。
- 缓存一致性:在多线程环境中,缓存一致性是确保多个线程之间共享的数据保持一致性的过程。
synchronized
块确保了在任何时候只有一个线程能够修改共享数据,从而避免了缓存不一致的问题。即使其他线程尝试读取或写入共享数据,由于它们被阻塞在锁之外,它们不能看到在工作内存中的修改,除非持有锁的线程释放锁并允许它们获取锁。
简而言之,synchronized
通过确保对共享资源的独占访问来强制工作内存与主内存的刷新,从而保证了缓存一致性。它确保了任何线程在访问或修改共享数据时都是实时的并且一致的。
3.3 synchronized 原理和例子
public class Counter {private int count = 0; // 共享资源:计数器// synchronized 块用于保护对 count 的并发访问public synchronized void increment() {count++; // 对共享资源的操作(这里是增加计数器的值)}public int getCount() {return count; // 外部访问共享资源(可能需要同步)}public static void main(String[] args) throws InterruptedException {Counter counter = new Counter(); // 创建 Counter 实例对象// 创建多个线程,模拟并发增加计数器的值for (int i = 0; i < 10; i++) { // 创建 10 个线程来并发增加计数器的值Thread thread = new Thread(() -> {for (int j = 0; j < 100; j++) { // 每个线程都尝试增加计数器值多次以模拟并发情况counter.increment(); // 使用 synchronized 块来安全地增加计数器值}});thread.start(); // 启动线程thread.join();} // 循环结束后,所有线程都已经启动并尝试增加计数器的值。由于使用了 synchronized 块,计数器的值将准确累积而不会发生冲突或重叠增加的情况。可以检查 getCount() 的返回值来验证这一点。System.out.println(counter.count);}
}
在字节码层面 synchronized 原理
-
方法同步: 对于使用
synchronized
修饰的方法,JVM会在方法的访问修饰符字节码指令之前插入一个特殊的指令,称为“ACC_SYNCHRONIZED”。这个标志告诉JVM该方法需要一个锁来执行。当线程调用这个方法时,它必须先获得对象的内置锁(即实例锁)。持有锁的线程可以在该对象的任何方法上执行任何操作,而不会阻塞其他线程对同一个对象的访问。当方法返回时,锁会被自动释放。 -
代码块同步: 对于使用
synchronized(obj)
修饰的代码块,Java编译器会在该代码块的起始和结束位置生成特定的字节码指令。具体来说,它会使用monitorenter
和monitorexit
指令。monitorenter
指令用于获取对象的内部锁,而monitorexit
指令用于释放该锁。这两个指令确保了同步代码块中的代码是原子的,并且不会被其他尝试获取同一锁的线程中断。如果在持有锁的过程中发生了异常,需要确保monitorexit
指令始终被执行以释放锁。
四、总结
在多线程编程中,线程之间的通信非常重要,它可以实现资源共享、任务分工、同步操作、数据传递和提高性能等功能。为了确保线程之间的通信的正确性和效率,可以使用volatile关键字和synchronized关键字。volatile关键字可以保证可见性和禁止指令重排序优化,而synchronized关键字可以保证对共享资源的同步访问,保证原子性和可见性。
相关文章:

java 线程之间通信-volatile 和 synchronized
你好,我是 shengjk1,多年大厂经验,努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注!你会有如下收益: 了解大厂经验拥有和大厂相匹配的技术等 希望看什么,评论或者私信告诉我! 文章目录 一…...

资源宝库网站!人人必备的神器!
面对网络中海量的内容,一个高效、便捷的网络导航工具,可以帮助我们快速查找使用网络资源。无论是职场精英还是学生党,使用导航网站都可以帮助我们提升效率。下面小编就来和大家分享一款资源宝库网站-办公人导航-实用的办公生活导航网站&#…...

Redis实战—优惠卷秒杀(锁/事务/代理对象的应用)
本博客为个人学习笔记,学习网站与详细见:黑马程序员Redis入门到实战 P50 - P54 目录 优惠卷秒杀下单功能实现 超卖问题 悲观锁与乐观锁 实现CAS法乐观锁 一人一单功能实现 代码优化 代码细节分析 优惠卷秒杀下单功能实现 Controller层…...

HTML星空特效
目录 写在前面 完整代码 代码分析 运行效果 系列文章 写在后面 写在前面 100行代码实现HTML星空特效。 完整代码 全部代码如下。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&g…...

银行数仓项目实战(四)--了解银行业务(存款)
文章目录 项目准备存款活期定期整存整取零存整取存本取息教育储蓄定活两便通知存款 对公存款对公账户协议存款 利率 项目准备 (贴源层不必写到项目文档,因为没啥操作没啥技术,只是数据。) 可以看到,银行的贴源层并不紧…...

MySQL版本发布模型
MySQL 8.0 之后使用了新的版本控制和发布模型,分为两个主线:长期支持版(LTS)以及创新版。这两种版本都包含了缺陷修复和安全修复,都可以用于生产环境。 下图是 MySQL 的版本发布计划: 长期支持版 MySQL…...
java: 不兼容的类型: org.apache.xmlbeans.XmlObject无法转换为x2006.main.CTRow
我使用的xmlbeans版本是5.0,使用xmlbeans包做转换时,报错,正如标题显示得那样 解决办法 额外再引入下面的jar包 <dependency><groupId>org.apache.xmlbeans</groupId><artifactId>xmlbeans</artifactId><…...

内容时代:品牌如何利用社交平台精准触达用户
还记得学生时代老师教写作文的时候常说的一句话就是“开头质量决定了阅卷老师想不想花精力去读,而内容质量决定了她愿不愿意给你判高分”这个世界仿若一个巨大的圆,同样的逻辑放在任何地方好像都能适用。在品牌营销中,内容已成为品牌与消费者…...
推荐4款PC端黑科技工具,快来看看,建议收藏
Thunderbird Thunderbird 是由 Mozilla 基金会开发的一款免费且开源的电子邮件客户端,支持 Windows、macOS、Linux 等多种操作系统。它不仅可以用于发送和接收电子邮件,还可以作为新闻阅读器、聊天工具以及日历应用。 Thunderbird 提供了丰富的功能&…...

汉化版PSAI全面测评,探索国产AI绘画软件的创新力量
引言 随着AI技术的飞速发展,图像处理和绘画领域迎来了新的变革。作为一名AIGC测评博主,今天我们测评的是一款国产AI绘画软件——StartAI,一句话总结:它不仅在技术上毫不逊色于国际大牌,更在用户体验和本地化服务上做到…...

LeetCode | 709.转换成小写字母
这道题可以用api也可以自己实现,都不难,大小字母之前相差了32,检查到大写字母时加上32即可 class Solution(object):def toLowerCase(self, s):""":type s: str:rtype: str"""return s.lower()class Solution…...

洗地机哪个品牌比较好?四款好用靠谱的优质洗地机推荐
随着现代生活节奏的加快,家庭清洁成了一项耗时且繁琐的任务。洗地机凭借其智能化和高效的清洁能力,越来越受到大家的青睐。然而,市场上各种品牌和型号琳琅满目,让人眼花缭乱。为了帮助大家在众多选择中找到心仪的产品,…...

java:spring actuator添加自定义endpoint
# 项目代码资源: 可能还在审核中,请等待。。。 https://download.csdn.net/download/chenhz2284/89437274 # 项目代码 【pom.xml】 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId&…...
LeetCode88-删除有序数组中的重复项
题目 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 代…...
SpringBoot Starter 通用接口加密组件(防篡改)+ RequestBodyAdvice和ResponseBodyAdvice原理
防篡改: 如何保证接口安全,做到防篡改防重放?_接口防止串改-CSDN博客 接口安全设计之防篡改和防重放_接口防篡改机制-CSDN博客 参考博客: RequestBodyAdvice和ResponseBodyAdvice原理详解-CSDN博客 SpringBoot Starter 通用接口…...

delphi 如何使用TEdgeBrowser组件以及打包环境在其他主机上运行
不管开发环境还是第三方环境先安装运行时库:Microsoft Edge WebView2 | Microsoft Edge Developer 开发环境可以直接通过: delphi IDE安装 安装完毕后进入到指定路径,复制里面的WebView2Loader.dll到你要开发的程序根目录: 大致路…...

Sui的Fastcrypto加密库刷新速度记录
Sui使用的加密库Fastcrypto打破了许多速度记录,Mysten Labs在基准测试和安全分析中的工作修复了许多安全漏洞,同时通过识别新的优化技巧为创新开辟了道路。 最近在伦敦帝国理工学院举行的国际性能工程会议(ICPE)基准测试研讨会上…...
Malformed \uxxxx encoding或Maven server structure problem问题解决
问题描述: idea运行项目时, 报错如下: [ERROR] Malformed \uxxxx encoding. [ERROR] Maven server structure problem [ERROR] Malformed \uxxxx encoding. 解决方法总结 先说一下解决方法无非是下面几种 1、先检查项目的.properties、.yml 、pom.xml、logback等…...

Sui主网升级至V1.27.2版本
其他升级要点如下所示: 重点: #17245 增加了一个新的协议版本,并在开发网络上启用了Move枚举。 JSON-RPC #17245: 在返回的JSON-RPC结果中增加了对Move枚举值的支持。 GraphQL #17245: 增加了对Move枚举值和类型的支持。 CLI #179…...

Cheat Engine 学习
文章目录 Exact Value scanning任务实现步骤Unknown initial value任务实现步骤原理说明Floating points任务实现步骤原理说明Code finder任务实现步骤原理说明Pointers任务实现步骤原理说明Change Pointer 操作:Active(活跃状态)和数值修改:Code Injection任务概述实现步骤…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...