多线程-锁的种类
1 作用
Java中的锁主要用于保障多并发线程情况下数据的一致性。在多线程编程中为了保障数据的一致性,我们通常需要在使用对象或者方法之前加锁,这时如果有其他线程也需要使用该对象或者该方法,则首先要获得锁,如果某个线程发现锁正在被其他线程使用,就会进入阻塞队列等待锁的释放.直到其他线程执行完成并释放锁、该线程才有机会再次获取锁进行操作。这样就保障了在同一时刻只有一个线程持有该对象的锁并修改对象、从而保障数据的安全。
锁从乐观和悲观的角度可分为乐观锁和悲观锁,从获取资源的公平性角度可分为公平锁和非公平锁,从是否共享资源的角度可分为共享锁和独占锁,从锁的状态的角度可分为偏向锁、轻量级锁和重量级锁。同时,在JVM中还巧妙设计了自旋锁以更快地使用CPU资源。
2 乐观锁、悲观锁
-
乐观锁
乐观锁采用乐观的思想处理数据,在每次读取数据时都认为别人不会修改该数据,所以不会上锁,但在更新时会判断在此期间别人有没有更新该数据、通常采用在写时先读出当前版本号然后加锁的方法。具体过程为:比较当前版本号与上一次的版本号,如果版本号一致.则更新,如果版本号不一致,则重复进行读、比较、写操作。
-
悲观锁
悲观锁采用悲观思想处理数据,在每次读取数据时都认为别人会修改数据、所以每次在读写数据时都会上锁,这样别人想读写这个数据时就会阻塞、等待直到拿到锁。
Java 中的悲观锁大部分基于AQS(Abstract Qucued Synchronized,抽象的队列同步器)架构实现。AQS定义了一套多线程访问共享资源的同步框架,许多同步类的实现都依赖于它,例如常用的Synchronized、ReentrantLock、Semaphore、CountDownLatch等。该框架下的锁会先尝试以 CAS 乐观锁去获取锁、如果获取不到,则会转为悲观锁(如RetreenLock )。
比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。
3 公平锁、非公平锁
公平锁
概念: 是指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁。
好处:公平锁的优点是等待锁的线程不会饿死。
缺点:是整体吞吐效率相对非公平锁要低,等待队列中除第一个线程以外的所有线程都会阻塞,CPU唤醒阻塞线程的开销比非公平锁大。
非公平锁
概念:非公平锁是多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以有可能出现后申请锁的线程先获取锁的场景
好处:非公平锁的优点是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程。
缺点:处于等待队列中的线程可能会饿死,或者等很久才会获得锁。
4 可重入锁、非可重入锁
可重入锁又名递归锁,是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。Java中ReentrantLock和synchronized都是可重入锁,可重入锁的一个优点是可一定程度避免死锁。
5 共享锁、排它锁
共享锁和排它锁多用于数据库中的事物操作,主要针对读和写的操作。而在 Java 中,对这组概念通过 ReentrantReadWriteLock 进行了实现,它的理念和数据库中共享锁与排它锁的理念几乎一致,即一条线程进行读的时候,允许其他线程进入上锁的区域中进行读操作;当一条线程进行写操作的时候,不允许其他线程进入进行任何操作。即读 + 读可以存在,读 + 写、写 + 写均不允许存在。
共享锁:也称读锁或 S 锁。如果事务 T 对数据 A 加上共享锁后,则其他事务只能对 A 再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据。
排它锁:也称独占锁、写锁或 X 锁。如果事务 T 对数据 A 加上排它锁后,则其他事务不能再对 A 加任何类型的锁。获得排它锁的事务即能读数据又能修改数据。
6 自旋锁
-
自旋锁认为:如果持有锁的线程能在很短的时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞、挂起状态,只需等一等(也叫作自旋),在等待持有锁的线程释放锁后即可立即获取锁,这样就避免了用户线程在内核状态的切换上导致的锁时间消耗。
-
线程在自旋时会占用CPU,在线程长时间自旋获取不到锁时,将会产CPU 的浪费,甚至有时线程永远无法获取销而导致CPU 资源被永久占用,所以需要设定一个自旋等待的最大时间。在线程执行的时间超讨自旋等待的
-
自旋锁的优缺点如下。
-
优点:自旋锁可以减少CPU上下文的切换,对于占用锁的时间非常短或锁竞争不激烈的代码块来说性能大幅度提升,因为自旋的 CPU 耗时明显少于线程阻塞、挂起、再唤醒时两次CPU上下文切换所用的时间。
-
缺点:在持有锁的线程占用锁时间过长或锁的竞争过于激烈时,线程在自旋过程中会长时间获取不到锁资源,将引起 CPU 的浪费。所以在系统中有复杂锁依赖的情况下不适合采用自旋锁。
-
-
2.自旋锁的时间阈值
-
自旋锁用于让当前线程占着CPU 的资源不释放,等到下次自旋获取锁资源后立即执行相关操作。但是如何选择自旋的执行时间呢?如果自旋的执行时间太长,则会有大量的线程处于自旋状态且占用CPU资源,造成系统资源浪费。因此、对自旋的周期选择将直接影响到系统的性能!
-
JDK的不同版本所采用的自旋周期不同,JDK 1.5为固定的时间,JDK 1.6引入了适应性自旋锁。适应性自旋锁的自旋时间不得是固定值,而是由上一次在同一个锁上的自旋时间及锁的拥有者的状态来决定的,可基本认为一个线程上下文切换的时间是就一个最佳时间。
-
7 重量级锁和轻量级锁
-
重量级锁是基于操作系统的互斥量(Mutex Lock)而实现的锁,会导致进程在用户态与内核态之间切换,相对开销较大。
-
synchronized在内部基于监视器锁(Monitor)实现,监视器锁基于底层的操作系统的 Mutex Lock实现,因此 synchronized属于重量级锁。重量级锁需要在用户态和核心态之间做转换,所以synchronized的运行效率不高。
-
JDK在1.6版本以后,为了减少获取锁和释放锁所带来的性能消耗及提高性能,引人了轻量级锁和偏向锁。
-
轻量级锁是相对于重量级锁而言的。轻量级锁的核心设计是在没有多线程竞争的前提下,减少重量级锁的使用以提高系统性能。轻量级锁适用于线程交替执行同步代码块的情况(即互斥操作),如果同一时刻有多个线程访问同一个锁,则将会导致轻量级锁膨胀为重量级锁。
-
轻量级锁也叫自旋锁。
8 偏向锁
-
除了在多线程之间存在竞争获取锁的情况,还会经常出现同一个锁被同一个线程多次获取的情况。偏向锁用于在某个线程获取某个锁之后,消除这个线程锁重人的开销,看起来似乎是这个线程得到了该锁的偏向(偏袒)。
-
偏向锁的主要目的是在同一个线程多次获取某个锁的情况下尽量减少轻量级锁的执行路径、因为轻量级锁的获取及释放需要多次CAS ( Compare and Swap )原于操作,而偏向锁只需要在切换 ThreadID 时执行一次 CAS 原子操作,因此可以提高钡的运行效率。
-
在出现多线程竞争锁的情况时,JVM 会自动撤销偏向锁,因此偏向锁的撤销操作的耗时必须少于节省下来的 CAS原子操作的耗时。
-
综上所述,轻量级锁用于提高线程交替执行同步块时的性能,偏向锁则在某个线程交替执行同步块时进一步提高性能。
-
锁的状态总共有4种:无锁、偏向锁、轻量级锁和重量级锁。随着锁竞争越来越激烈,锁可能从偏向锁升级到轻量级锁,再升级到重量级锁,但在Java 中锁只单向升级,不会降级。
-
hashtable
9 分段锁
-
分段锁并非一种实际的锁,而是一种思想,用于将数据分段并在每个分段上都单独加锁,把锁进一步细粒度化,以提高并发效率。ConcurrentHashMap在内部就是使用分段锁实现的。
9 CAS
CAS:Compare and Swap,即比较再交换。
dk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁。
对CAS的理解,CAS是一种无锁算法,CAS有3个操作数,要更新的变量V,旧的预期值E,要修改的新值N。当且仅当V和E相同的情况下,将内存值V修改为N,否则什么都不做。
10 ABA问题
ABA问题是指在CAS操作时,其他线程将变量值A改为了B,但是又被改回了A,等到本线程使用期望值A与当前变量进行比较时,发现变量A没有变,于是CAS就将A值进行了交换操作,但是实际上该值已经被其他线程改变过。 解决办法: 在变量前面加上版本号,每次变量更新的时候变量的版本号都+1,即A->B->A就变成了1A->2B->3A。只要变量被某一线程修改过,变量对应的版本号就会发生递增变化,从而解决了ABA问题。
11 锁升级
没有优化以前,synchronized是重量级锁(悲观锁),使用 wait 和 notify、notifyAll 来切换线程状态非常消耗系统资源;线程的挂起和唤醒间隔很短暂,这样很浪费资源,影响性能。所以 JVM 对 synchronized 关键字进行了优化,把锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。 锁的级别从低到高依次为:无锁 -> 偏向锁 -> 轻量级锁 -> 重量级锁,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。
1、无锁: 没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功,其他修改失败的线程会不断重试直到修改成功。
2、偏向锁: 偏向锁的核心思想就是锁会偏向第一个获取它的线程,该线程是不会主动释放偏向锁的,只有当其他线程尝试竞争偏向锁才会被释放。在接下来的执行过程中该锁没有其他的线程获取,则持有偏向锁的线程永远不需要再进行同步。
当一个线程访问同步块并获取锁的时候,会在对象头和栈帧中的锁记录里存储偏向的线程 ID,以后该线程在进入和退出同步块时不需要进行 CAS 操作来加锁和解锁,只需要检查当前 Mark Word 中存储的线程是否为当前线程,如果是,则表示已经获得对象锁;否则,需要测试 Mark Word 中偏向锁的标志是否为1,如果没有则使用 CAS 操作竞争锁,如果设置了,则尝试使用 CAS 将对象头的偏向锁指向当前线程。
偏向锁的撤销,需要在某个时间点上没有字节码正在执行时,先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着。如果线程不处于活动状态,则将对象头设置成无锁状态,并撤销偏向锁;如果线程处于活动状态,升级为轻量级锁的状态。
3、轻量级锁: 轻量级锁是指当锁是偏向锁的时候,被第二个线程 B 所访问,此时偏向锁就会升级为轻量级锁,线程 B 会通过自旋的形式尝试获取锁,线程不会阻塞,从而提高性能。
当前只有一个等待线程,则该线程将通过自旋进行等待。但是当自旋超过一定的次数时,轻量级锁便会升级为重量级锁;当一个线程已持有锁,另一个线程在自旋,而此时又有第三个线程来访时,轻量级锁也会升级为重量级锁。
4、重量级锁: 指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。
重量级锁将程序运行交出控制权,将线程挂起,由操作系统来负责线程间的调度,负责线程的阻塞和执行。这样会出现频繁地对线程运行状态的切换,线程的挂起和唤醒,消耗大量的系统资源,导致性能低下。
重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 实现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。
总结:锁的升级过程,如果只有一个线程获取到锁,这个锁就是偏向锁,因为对象头和栈帧中的锁记录里存储偏向的线程 ID,如果没有别的线程来竞争锁,那么直接执行代码;如果有别的线程在竞争锁,那么会释放偏向锁,线程会通过自旋的方式尝试获取锁,这个阶段的锁叫自旋锁(轻量级锁),如果经过多次自旋还是没有获取到锁,那么就会变成重量级锁。
原因:
假设有两个线程t1,t2
如果t1获取到锁以后,1ms以后就释放锁了,这时候用轻量级锁会更好一点,因为自旋锁不会释放资源,因为线程进入阻塞,就绪,CPU调度,竞争锁资源都是需要时间的,这中间的时间可能要几十毫秒,效率会比较低。
如果t1获取到锁以后,60s以后才释放锁,如果这时候t2一直处于自旋状态,自旋状态是不会释放锁的,一直占用cpu资源。
12 锁升级代码
(1) java对象组成
2 代码
新建maven项目,导入依赖
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
main方法中测试
import org.openjdk.jol.info.ClassLayout;public class Test {public static void main(String[] args) {A a = new A();System.out.println(ClassLayout.parseInstance(a).toPrintable());}
}
class A{public int a = 4;public long b = 5L;public boolean c = true;
}
结果:
3 mark word
mark word占用了8个字节(64位), markword的结构,定义在markOop.hpp文件:
4 查看hashcode
代码中添加
System.out.println(Integer.toHexString(a.hashCode()));
4 查看偏向锁
BiasedLockingStartupDelay表示系统启动几秒钟后启用偏向锁。默认为4秒,原因在于,系统刚启动时,一般数据竞争是比较激烈的,此时启用偏向锁会降低性能。由于这里为了测试偏向锁的性能,所以把延迟偏向锁的时间设置为0
JVM参数设置: -XX:BiasedLockingStartupDelay=0
代码:
public class Test {public static void main(String[] args) {A a = new A();
// System.out.println(Integer.toHexString(a.hashCode()));System.out.println(ClassLayout.parseInstance(a).toPrintable());synchronized (a){System.out.println(ClassLayout.parseInstance(a).toPrintable());}synchronized (a){System.out.println(ClassLayout.parseInstance(a).toPrintable());}}
}
class A{public int a = 4;public long b = 5L;public boolean c = true;
}
5 查看轻量级锁
package com.yang.test;import org.openjdk.jol.info.ClassLayout;public class Test {public static void main(String[] args) {A a = new A();
// System.out.println(Integer.toHexString(a.hashCode()));System.out.println(ClassLayout.parseInstance(a).toPrintable());synchronized (a){System.out.println(ClassLayout.parseInstance(a).toPrintable());}synchronized (a){System.out.println(ClassLayout.parseInstance(a).toPrintable());}new Thread(()->{synchronized (a){System.out.println(ClassLayout.parseInstance(a).toPrintable());}}).start();}
}
class A{public int a = 4;public long b = 5L;public boolean c = true;
}
6 重量级锁
package com.yang.test;import org.openjdk.jol.info.ClassLayout;public class Test2 {private static Object lock = new Object();public static void main(String[] args) throws InterruptedException {// 去掉偏向锁延时操作System.out.println(ClassLayout.parseInstance(lock).toPrintable()); //无锁new Thread(()->{System.out.println("子线程获取锁之前打印对象头信息");System.out.println(ClassLayout.parseInstance(lock).toPrintable()); //无锁synchronized (lock){try {System.out.println("子线程获取到锁打印对象头信息");System.out.println(ClassLayout.parseInstance(lock).toPrintable());Thread.sleep(5000);System.out.println("---子线程----");} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("子线程释放锁打印对象头信息");System.out.println(ClassLayout.parseInstance(lock).toPrintable());},"子线程").start();Thread.sleep(1000);sync();}public static void sync(){synchronized (lock){System.out.println("主线程获取到锁打印对象头信息");System.out.println(ClassLayout.parseInstance(lock).toPrintable());}}
}
关于线程id和hashcode的问题
HotSpot VM的锁实现机制是:
当一个对象已经计算过identity hash code,它就无法进入偏向锁状态; 当一个对象当前正处于偏向锁状态,并且需要计算其identity hash code的话,则它的偏向锁会被撤销,并且锁会膨胀为轻量级锁或者重量锁; 轻量级锁的实现中,会通过线程栈帧的锁记录存储Displaced Mark Word;重量锁的实现中,ObjectMonitor类里有字段可以记录非加锁状态下的mark word,其中可以存储identity hash code的值。
相关文章:
多线程-锁的种类
1 作用 Java中的锁主要用于保障多并发线程情况下数据的一致性。在多线程编程中为了保障数据的一致性,我们通常需要在使用对象或者方法之前加锁,这时如果有其他线程也需要使用该对象或者该方法,则首先要获得锁,如果某个线程发现锁正在被其他线程使用,就会…...
Hive 和 HDFS、MySQL 之间的关系
文章目录 HiveHDFSMySQL三者的关系 Hive、MySQL 和 HDFS 是三个不同的数据存储和处理系统,它们在大数据生态系统中扮演不同的角色,但可以协同工作以支持数据管理和分析任务。 Hive Hive 是一个基于 Hadoop 生态系统的数据仓库工具,用于管理和…...
【面试题】如何实现数组去重的?有几种方式?
前端面试题库 (面试必备) 推荐:★★★★★ 地址:前端面试题库 【国庆头像】- 国庆爱国 程序员头像!总有一款适合你! 1. 方法一:利用两层循环数组的splice方法 通过两层循环对数组…...
使用TCP方式拉取Canal数据
1 Canal对接Kafka联调 1.1 配置修改 canal.properties 修改 zk: canal.zkServers 10.51.50.219:2181instance.properties 开启配置项: canal.mq.dynamicTopic 是 Canal 的 MQ 动态 Topic 配置项: test_javaedge_01 是kafka 的 topicte…...
Docker安装mysql实战说明
安装前准备 在安装MySQL之前,你需要确保已经正确安装和配置了Docker,可以通过以下命令检查Docker是否已正确安装: docker --version如果Docker已经成功安装,你将看到Docker的版本信息。 下载mysql的镜像 Docker Hub是一个存储…...
前端DOM操作精解:基础概念、方法与最佳实践
引言 本文将深入探讨前端开发中的DOM操作,包括基础概念、常用方法和最佳实践。通过清晰易懂的解释和实际案例分析,我们将一起了解如何最有效地使用DOM操作来提升前端应用的用户体验。 一、DOM操作入门 在深入探讨DOM操作之前,我们先要理解…...
python sorted函数详解2023.9.11
sorted函数详解 1. 输入和输出2. key传入函数 1. 输入和输出 help(sorted) Help on built-in function sorted in module builtins: sorted(iterable, /, *, keyNone, reverseFalse)Return a new list containing all items from the iterable in ascending order.A custom k…...
Spring Reactive:响应式编程与WebFlux的深度探索
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
Qt应用开发(基础篇)——工具按钮类 QToolButton
一、前言 QToolButton类继承于QAbstractButton,该部件为命令或选项提供了一个快速访问按钮,通常用于QToolBar中。 按钮基类 QAbstractButton QToolButton是一个特殊的按钮,一般显示文本,只显示图标,结合toolBar使用。它…...
【数据结构面试题】栈与队列的相互实现
目录 1.队列实现栈 1.1创建栈 1.2判断是否为空 1.3入栈 1.4出栈 1.5获取栈顶元素 1.6完整代码 2. 用栈实现队列 2.1创建队列 2.2判断是否为空 2.3入队列 2.4出队列 2.5获取队头元素 2.6完整代码 1.队列实现栈 用队列实现栈https://leetcode.cn/problems/impleme…...
华为认证和红帽认证哪个比较好考呢
华为认证和红帽认证的考试难度、学习内容、适用范围等方面都有所不同,因此哪个比较好考要视具体情况而定: 考试难度:红帽认证的考试难度较高,需要考生具备较高的技术水平和实践经验;而华为认证则更注重基础知识的考察…...
[Java]_[中级]_[使用okhttp3和HttpClient代理访问外部网络]
场景 Java的http库常用的有HttpClient和Okhttp3, 如果公司有限制网络访问,需要代理才可以访问外网,那么如何使用代理Proxy? <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient<…...
ubuntu 20.04 docker 安装 mysql
要在Ubuntu 20.04上安装Docker并运行MySQL容器,您可以按照以下步骤操作: 1.更新系统包列表: sudo apt update2.安装Docker: sudo apt install docker.io3.启动Docker服务并设置其开机自启动: sudo systemctl start…...
C++在C语言基础上的优化
目录 一、命名空间 1、命名空间的定义 2、命名空间的使用 二、输入&输出 三、缺省参数 1、缺省参数的概念 2、缺省参数的分类 四、函数重载 五、引用 1.引用的概念 2.引用的特性 3、引用和指针的区别 六、内联函数 七、基于范围的for循环 一、命名空间 命名空…...
分享一个python实验室设备预约管理系统 实验室设备维修系统源码 lw 调试
💕💕作者:计算机源码社 💕💕个人简介:本人七年开发经验,擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等,大家有这一块的问题可以一起交流! 💕&…...
兵者多诡(HCTF2016)
环境:https://github.com/MartinxMax/CTFer_Zero_one 题目简介 解题过程 登录首页 提交png图片上传抓包,可以看到是向upload文件提交数据 在fp参数中尝试伪协议读取home.php文件 http://127.0.0.1:88/HCTF2016-LFI/home.php?fpphp://filter/readconvert.base64…...
【JAVA-Day04】Java关键字和示例:深入了解常用关键字的用法
Java关键字和示例:深入了解常用关键字的用法 摘要Java 关键字、标识符和命名规范一、Java 关键字常用关键字DEMO1. 示例代码使用 if 和 else 关键字:2. 示例代码使用 for 循环:3. 示例代码使用 switch 关键字:4. 示例代码使用 wh…...
Android请求网络报错:not permitted by network security policy
一、错误记录 https的接口请求正常的, 请求http的接口时报错:not permitted by network security policy 二、问题分析 原因: 由于 Android P(版本27以上) 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉。如果当…...
python报错:ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1
python报错:ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1 问题分析 说明:requests包引入了urllib3,而新版本的urllib3 需要OpenSSL 1.1.1以上版本,否则报错: ImportError: urllib3 v2.0 only supports Ope…...
如何使用adb command来设置cpu频率和核数
透過ADB Shell設定CPU開核與freq的command與用法如下: # Disable PPM echo 0 > /proc/ppm/enabled # Enable PPM (Default) echo 1 > /proc/ppm/enabled echo 0 > /proc/ppm/enabled Fixed # Core for each cluster echo X Y > /proc/ppm/policy/ut_fix_core_num …...
236. 二叉树的最近公共祖先
236. 二叉树的最近公共祖先 题目-中等难度示例1. dfs 题目-中等难度 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p…...
Git常见问题:git pull 和 git pull --rebase二者区别
git pull 和 git pull --rebase 都是从远程仓库获取最新的更改并将其合并到本地分支。但它们之间的区别在于合并方式。以下是它们之间的主要区别: git pull: 当你执行 git pull 时,Git 会执行以下两个操作: git fetchÿ…...
关于HarmonyOS元服务的主题演讲与合作签约
一、感言 坚持中,总会有很多意想不到的收获。 前几次参与HDC时更多的是观众、开发者、专家的身份,以参观、学习、交流为主。 通过几年的努力,和HarmonyOS功能成长,在2023年的HDC大会中,有了我的演讲,并带领…...
cache 学习
好文章: Cache的基本原理 - 知乎...
SSM - Springboot - MyBatis-Plus 全栈体系(六)
第二章 SpringFramework 四、SpringIoC 实践和应用 3. 基于 注解 方式管理 Bean 3.1 实验一:Bean 注解标记和扫描 (IoC) 3.1.1 注解理解 和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框…...
【Flutter】引入网络图片时,提示:Failed host lookup: ‘[图片host]‘
在使用 NetworkImage 组件加载外部图片时,提示 Failed host lookup: [图片host] 错误。 排查方向 1、清理缓存 解决方案: 尝试flutter clean清空缓存后重新安装依赖flutter pub get重新构建项目flutter create . 走完上述三个步骤后,再次…...
Python基础教程:索引和切片
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 索引(下标) 索引又称下标,用来表示可迭代对象中的某个元素的位置。 用正整数表示的索引值,从左向右定位,从 0 开始计数,如 0,1&#…...
JVM基础面试题
JDK、JRE、JVM的关系 JVM Java虚拟机,它只识别.class类型文件,它能将class文件中的字节码指令进行识别并调用操作系统向上的API完成动作。 JRE Java运行时环境。它主要包含两部分:Jvm的标准实现和Java的一些基本类库。相对于JVM来说,JRE多出来…...
蓝桥杯官网填空题(平方末尾)
题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。 能够表示为某个整数的平方的数字称为“平方数” 虽然无法立即说出某个数是平方数,但经常可以断定某个数不是平方数。 因为平方数的末位只可能是&#x…...
深入探究数据结构与算法:构建强大编程基础
文章目录 1. 为什么学习数据结构与算法?1.1 提高编程技能1.2 解决复杂问题1.3 面试准备1.4 提高代码效率 2. 学习资源2.1 经典教材2.2 在线学习平台2.3 学习编程社区 3. 数据结构与算法的实际应用3.1 排序算法3.2 图算法3.3 字符串匹配算法 4. 结论 🎉欢…...
看电视剧的免费网站/推广引流最快的方法
跨浏览器 跨域资源共享 解决方案参考文章: (1)跨浏览器 跨域资源共享 解决方案 (2)https://www.cnblogs.com/kasmine/p/6440571.html 备忘一下。...
wordpress的标签有什么用/seo整站优化多少钱
一、前言 时间子系统中的tick device layer主要涉及kernel/time/tick-*相关的文件,本文的主要内容就是从high level层次(不纠缠在具体的每行代码)描述tick device layer的运作逻辑。 如果说每个.c文件是一个模块的话,我们可以首…...
株洲信息网/宁波seo怎么做优化
美团已获得南京、上海、杭州、成都、温州等五个城市的网约车牌照,近日再获北京的网约车牌照,这显示出它很可能将在北京开展网约车业务,在网约车老大滴滴的大本营开展业务,无疑将再次印发滴滴与美团之间的大战,不过考虑…...
怎么建立自己企业网站/泉州百度seo
shell介绍 Shell 是一个 C 语言编写的脚本语言,它是用户与 Linux 的桥梁,用户输入命令交给 Shell 处理,shell是一个命令解释器,是一个工具箱, Shell 将相应的操作传递给内核(Kernel)࿰…...
wordpress在线客服插件/网络营销服务商有哪些
钩子方法 pytest_runtest_makereport 可以清晰的了解用例的执行过程,并获取到每个用例的执行结果。 钩子方法 pytest_runtest_makereport 源码: 按照执行顺序,具体过程如下: 1、先判断,当 report.when setup 时&…...
国外电商网站如何建立/站长seo软件
我正在尝试使用python构建一个简单的加密。在这是加密:from Crypto.Cipher import AESfrom Crypto.Util.Padding import padfrom Crypto.Util.Padding import unpadBLOCK_SIZE 32def encrypt(message):obj AES.new(bThis is a key123, AES.MODE_CBC, bThis is an …...