当前位置: 首页 > news >正文

多线程面试题汇总

多线程面试题汇总

  • 一、多线程
    • 1、线程的生命周期
    • 2、线程的创建(函数创建)
    • 3、线程的创建(使用类)
    • 4、守护线程
  • 二、全局解释器锁
    • 1、使用单线程实现累加到500000000
    • 2、使用多线程实现累加到500000000
    • 3、总结
  • 三、线程安全
    • 1、多线程之数据混乱问题
    • 2、有了全局解释器锁(GIL)为什么还需要同步锁?
    • 3、同步锁
      • 3.1、加同步锁(with方法)
      • 3.2、加同步锁(acquire方法和release方法)
  • 四、锁
    • 1、同步锁
    • 2、递归同步锁
    • 3、条件锁
    • 4、事件锁
    • 5、信号量锁
  • 五、死锁
    • 1、案例:鱼和熊掌不可兼得问题
  • 六、进程与线程的区别

一、多线程

1、线程的生命周期

在这里插入图片描述
1、线程的创建:t=threading.Thread()
2、就绪状态:已经获得了除CPU之外的其他资源,正在参与调度,等待被执行,当调度完成之后,立即运行
3、启动状态:获得了CPU时间片段,正在运行
4、等待\阻塞状态:遇到time.sleep()时,会阻塞,暂时不参与调度,等待事件发生
5、中止状态:线程运行结束,run函数运行结束,等待系统回收其线程资源。

2、线程的创建(函数创建)

在这里插入图片描述
在这里插入图片描述

3、线程的创建(使用类)

t=MyThread(name=s[i]) 创建线程,里面的参数代表线程的名字,如果不传,系统会默认有一个名字
在这里插入图片描述

4、守护线程

当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程就分兵两路,分别运行,那么当主线程完成想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是只要主线程完成了,不管子线程是否完成,都要和主线程—起退出,这时就可以用setDaemon方法
在这里插入图片描述
输出结果:线程2还没有完整的执行完毕,遇到守护线程就终止执行了。
在这里插入图片描述
t.setDaemon(True) 当前的子线程设置为守护线程
守护线程:随着主线程的终止而终止,不管当前主线程下有多少子线程没有执行完毕,都会终。

二、全局解释器锁

1、GIL锁不是python的特点。而是cpython的特点。

每个线程在执行的时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU。在CPython中,每一个Python线程执行前都需要去获得GIL锁,获得该锁的线程才可以执行,没有获得的只能等待,当具有GIL锁的线程运行完成后,其他等待的线程就会去争夺GIL锁,这就造成了,在Python中使用多线程,但同一时刻下依旧只有一个线程在运行,所以Python多线程其实并不是「并行」的,而是「并发」。

1、使用单线程实现累加到500000000

import time,threadingdef task(n):sum=0while sum<n:sum+=1print(f'最后累加哦结果为:{sum}')if __name__ == '__main__':# 单线程start=time.time()task(500000000)end=time.time()print(f'单线程结束后,一共运行的时间为:{end-start}')

在这里插入图片描述

2、使用多线程实现累加到500000000

import time,threadingdef task(n):sum=0while sum<n:sum+=1print(f'最后累加哦结果为:{sum}')if __name__ == '__main__':# 多线程start = time.time()t1=threading.Thread(target=task,args=(250000000,))t2=threading.Thread(target=task,args=(250000000,))t1.start()t2.start()t1.join()t2.join()end=time.time()print(f'单线程结束后,一共运行的时间为:{end-start}') # todo 15.777813196182251

在这里插入图片描述
发现问题:两个线程同时执行并不能比单个线程的执行快
由此发现:CPU密集型(计算密集型)任务采用多线程执行并不能提高计算速度

3、总结

GIL解决办法:

  • 使用其他语言写的python解析器(不推荐,还是用python官方的CPython好)
    • JPython、pypy
  • 不使用多线程,使用多进程-进程里面加协程实现多任务来充分利用多核CPU(推荐)
  • 即使存在GIL,在有IO等待操作的程序中,还是多线程快;当然没有资源等待的还是使用单线程快(科学计算、累加等等)

但是需要注意的是线程有了GIL后并不意味着使用python多线程时不需要考虑线程安全,GIL的存在是为了方便使用C语言CPython解释器的编写者,而顶层使用python时依旧要考虑线程安全。

三、线程安全

当多个线程同时访问一个对象时,不管如何计算,如果调用这个对象的行为都可以获得正确的结果,那就称这个对象时线程安全的。如果出现了“脏数据”。则线程不安全。
脏数据:产生脏数据的原因是,当一个线程在对数据进行修改时,修改到一半时另一个线程读取了未经修改的数据并进行修改。

如何避免脏数据的产生呢?一个办法就是用join方法,即先让一个线程执行完毕再执行另一个线
程。但这样的本质是把多线程变成了单线程,失去了多线程的意义。另一个办法就是用线程锁。

1、多线程之数据混乱问题

在这里插入图片描述
在这里插入图片描述
但是当我把累加次数设置小,就不会出现数据混乱问题
在这里插入图片描述
数据混乱的原因:
cpu分成多个时间片段,启动10线程,分配10个cpu时间片段,当我累加数字设置比较小的时候,在单个cpu时间片段内,for循环代码就执行完,就不会产生数据混乱的。当我数据设置的比较大时,在单个cpu时间片段内,for循环代码就执行不完,并且没有分配2个或2个以上的连续的cpu时间片段,导致一个cpu时间片段没有执行完该线程,下一个线程开始执行了

2、有了全局解释器锁(GIL)为什么还需要同步锁?

全局解析器锁(GIL)加在了全局了,没有加到我所想要的位置,加到什么位置不是我们决定的;
包括修改资源的程序和非修改资源的程序,如果出现在修改资源的相关代码上,肯定会出现脏数据。
同步锁:来获取一把互斥锁。互斥锁就是对共享数据进行锁定,保证同一时刻只有一个线程操作数据,是数据级别的锁。
GIL锁是解释器级别的锁,保证同一时刻进程中只有一个线程拿到GIL锁,拥有执行权限。

2个线程执行任务造成数据混乱

import threading
num=0
def work():global numfor i in range(1000000):num+=1print('work',num)def work1():global numfor i in range(1000000):num+=1print('work1',num)if __name__ == '__main__':t1=threading.Thread(target=work)t2=threading.Thread(target=work1)t1.start()t2.start()t1.join()t2.join()print('主线程执行结果',num)

执行结果:明显数据混乱了

work work1 16347351376208

主线程执行结果 1634735

说明:

代码中:num+=1,可以拆解为
num=100
100+1
num=101
同步锁这3行代码执行完毕了才会释放锁

3、同步锁

同一时刻的一个进程下的一个线程只能占用CPU,要确保这个线程下的程序在一段时间内被CPU执行,那么就要用到同步锁,只需要在对公共数据的操作前后加上上锁和释放锁的操作即可。

3.1、加同步锁(with方法)

from threading import Lockimport threading
num=0
def work():global numfor i in range(1000000):with lock:num+=1print('work',num)def work1():global numfor i in range(1000000):with lock:num+=1print('work1',num)if __name__ == '__main__':lock=Lock()t1=threading.Thread(target=work)t2=threading.Thread(target=work1)t1.start()t2.start()t1.join()t2.join()print('主线程执行结果',num)

work 1845334work1 2000000

主线程执行结果 2000000

3.2、加同步锁(acquire方法和release方法)

from threading import Lockimport threading
num=0
def work():global numfor i in range(1000000):lock.acquire()num+=1lock.release()print('work',num)def work1():global numfor i in range(1000000):lock.acquire()num += 1lock.release()print('work1',num)if __name__ == '__main__':lock=Lock()t1=threading.Thread(target=work)t2=threading.Thread(target=work1)t1.start()t2.start()t1.join()t2.join()print('主线程执行结果',num)

workwork1 1921583
2000000
主线程执行结果 2000000

四、锁

锁是python提供给我们能够自行操控线程切换的一种手段,使用锁可以让线程的切换变得有序。
一旦线程的切换变的有序后,各个线程之间对数据的访问、修改就变得可控,所以若要保证线程安全,就必须使用锁。

threading模块中提供了5种最常见的锁,下面是按照功能进行划分:

  • 同步锁:Lock(一次只能放行一个)
  • 递归锁:RLock(一次只能放行一个)
  • 条件锁:condition(一次可以放行任意个)
  • 事件锁:event(一次全部放行)
  • 信号量锁:semaphore(一次可以放行特定个)

1、同步锁

上面已讲解

2、递归同步锁

在同步锁的基础上可以做到连续重复使用多次acquire()后再重复使用多次release()的操作,但是一定要注意加锁次数和解锁次数必须一致,否则也将引发死锁现象。
递归锁RLock:它内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。

3、条件锁

条件锁是在递归锁的基础上增加了能够暂停线程运行的功能。并且我们可以使用wait()和notify()来控制线程执行的个数。
注意:条件锁可以自由设定一次放行几个线程。

lock.notify(number):有条件的唤醒线程
lock.wait() :让当前线程暂停。并等待
但是不能唤醒特定某个线程

from threading import Thread,Condition,current_thread#全局变量
g_number = 0#子线程的数量
sub_thread_count=10#正在运行的线程数量
current_run_thread_count=0#创建一个条件锁
lock=Condition()def task():global g_number,current_run_thread_countthread_name=current_thread().name  #当前线程的名字with lock:print(f'{thread_name}线程得到锁,并直接进入等待状态')lock.wait() #让当前线程暂停。并等待print(f'{thread_name}线程已经苏醒了,并执行后面的代码')g_number+=1current_run_thread_count+=1if __name__ == '__main__':thread_list=[]for i in range(sub_thread_count):t=Thread(target=task,name=f't{i+1}')thread_list.append(t)t.start()while current_run_thread_count<sub_thread_count:# 由用户输入number=int(input("请输入你要唤醒几个线程,数字:"))with lock:lock.notify(number)print('主线程执行结束')

运行代码
每个线程都能得到这把锁,并进入等待状态,此时线程到13行代码已经阻塞了。10个线程都已经调用了wait()函数
在这里插入图片描述
现在需要唤醒4个线程,输入数字4,t1,t2,t3,t4线程被唤醒
在这里插入图片描述
再唤醒4个线程,t5~t8被唤醒
在这里插入图片描述

4、事件锁

事件锁是基于条件锁来做的,它与条件锁的区别在于一次只能放行全部,不能放行任意个数量的子线程继续运行。
我们可以将事件锁看为红绿灯,当红灯时所有子线程都暂停运行,并进入“等待”状态,当绿灯时所有子线程都恢复“运行”

eventLock.set() 设置绿灯
eventLock.clear() 设置红灯
eventLock.wait() 暂停运行,等待绿灯

import threadingmaxSubThreadNumber = 3  #最多子线程为3def task():thread_name = threading.current_thread().name   #获取当前线程的名字print("线程开始启动,并马上进入等待状态:%s" % thread_name)eventLock.wait()  # 暂停运行,等待绿灯print("第一次绿灯打开,线程往下走:%s " % thread_name)eventLock.wait()  # 暂停运行,等待绿灯print("第二次绿灯打开,线程往下走:%s" % thread_name)if __name__ == '__main__':eventLock = threading.Event()for i in range(maxSubThreadNumber):subThreadIns = threading.Thread(target=task)subThreadIns.start()eventLock.set() #设置绿灯eventLock.clear()   #设置红灯eventLock.set()

在这里插入图片描述

5、信号量锁

Semaphore()
信号量锁也是根据条件锁来做的,它与条件锁的区别如下:
条件锁:一次可以放行任意个处于 “等待” 状态的线程
事件锁:一次可以放行全部的处于 “等待” 状态的线程
信号量锁:通过规定,成批的放行特定个处于 “上锁” 状态的线程

import threading
import timemaxSubThreadNumber = 6def task():thread_name = threading.currentThread().namewith semaLock:print("线程获得锁,开始运行:%s" % thread_name)time.sleep(3)if __name__ == '__main__':semaLock = threading.Semaphore(2)for i in range(maxSubThreadNumber):subThreadIns=threading.Thread(target=task)subThreadIns.start()

五、死锁

在多线程程序中,死锁问题很大一部分原因是由于线程同时获取多个锁造成的。
在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
3、尽管死锁很难发生,但一旦发生就会造成应用的停止响应。

在这里插入图片描述

1、案例:鱼和熊掌不可兼得问题

import threading
import time# 代表鱼的锁
mutex_Yu = threading.Lock()
# 代表熊掌的锁
mutex_Xiongzhang = threading.Lock()class MyThread1(threading.Thread):def run(self):mutex_Yu.acquire()  # 得到🐟print('线程1已经得到鱼了')time.sleep(1)mutex_Xiongzhang.acquire()print('线程1得到熊掌')mutex_Xiongzhang.release()mutex_Yu.release()class MyThread2(threading.Thread):def run(self):mutex_Xiongzhang.acquire()print('线程2已经得到熊掌了')time.sleep(1)mutex_Yu.acquire()print('线程2已经得到🐟了')mutex_Yu.release()mutex_Xiongzhang.release()if __name__ == '__main__':t1 = MyThread1()t2 = MyThread2()t1.start()t2.start()

在这里插入图片描述
解决方法:让多个线程交叉有序的竞争多个资源

#让多个线程交叉有序的竞争多个资源
import threading
import time
# 代表🐟的锁
mutex_Yu = threading.Lock()
# 代表熊掌的锁
mutex_Xiongzhang = threading.Lock()class MyThread1(threading.Thread):def run(self):while True:mutex_Yu.acquire()  # 得到🐟print('线程1已经得到鱼了')time.sleep(1)mutex_Yu.release()   #释放鱼对应锁mutex_Xiongzhang.acquire()  # 得到熊掌print('线程1得到熊掌')time.sleep(1)mutex_Xiongzhang.release()    #释放熊掌对应锁class MyThread2(threading.Thread):def run(self):while True:mutex_Xiongzhang.acquire()   # 得到熊掌print('线程2已经得到熊掌了')time.sleep(1)mutex_Xiongzhang.release() #释放熊掌对应锁mutex_Yu.acquire()     # 得到🐟print('线程2已经得到鱼了')time.sleep(1)mutex_Yu.release()     #释放鱼对应锁if __name__ == '__main__':t1 = MyThread1()t2 = MyThread2()t1.start()t2.start()

六、进程与线程的区别

1、进程是操作系统分配任务的基本单位,进程是python中正在运行的程序;当我们打开1个浏览器时就是开启了一个浏览器进程;
线程是进程中执行任务的基本单位(执行指令集),一个进程中至少有一个线程,当只有一个线程时,称为主线程。
2、进程的创建和销毁消耗资源多;
线程的创建和销毁消耗资源少。
3、线程的切换速度比较快。
4、多进程中,进程与进程之间不能进行通信,如果需要通信需要借助Queue、Pipe;
一个进程中有多个线程时:线程之间可以进行直接通信。
5、多进程可以利用多核CPU:多进程的主要目的是充分利用多核CPU资源。
多线程不可以利用多核CPU:多线程的主要目的是充分利用好某一个单核。
6、进程的启动速度要比线程的启动速度慢。
7、进程与进程是不可以共享同一个数据的(同一个全局变量);
两个线程可以共享同一个进程中的一个数据(同一个全局变量)。
8、进程用到了Process类;
线程用到了Thread类。
9、进程可以独立存在;
线程不能独立存在,依赖进程存在。
10、多进程中不会出现数据混乱、死锁的问题;
多线程中会出现数据混乱、死锁的问题。


在这里插入图片描述

相关文章:

多线程面试题汇总

多线程面试题汇总 一、多线程1、线程的生命周期2、线程的创建&#xff08;函数创建&#xff09;3、线程的创建&#xff08;使用类&#xff09;4、守护线程 二、全局解释器锁1、使用单线程实现累加到5000000002、使用多线程实现累加到5000000003、总结 三、线程安全1、多线程之数…...

CentOS7.9+Kubernetes1.29.2+Docker25.0.3高可用集群二进制部署

CentOS7.9Kubernetes1.29.2Docker25.0.3高可用集群二进制部署 Kubernetes高可用集群&#xff08;Kubernetes1.29.2Docker25.0.3&#xff09;二进制部署二进制软件部署flannel v0.22.3网络&#xff0c;使用的etcd是版本3&#xff0c;与之前使用版本2不同。查看官方文档进行了解…...

STM32——OLED菜单(二级菜单)

文章目录 一.补充二. 二级菜单代码 简介&#xff1a;首先在我的51 I2C里面有OLED详细讲解&#xff0c;本期代码从51OLED基础上移植过来的&#xff0c;可以先看完那篇文章&#xff0c;在看这个&#xff0c;然后按键我是用的定时器扫描不会堵塞程序,可以翻开我的文章有单独的定时…...

配置Vite+React+TS项目

初始化 执行npm create vite并填写项目名、用那个框架。。 配置 路径别名 在vite.config.ts里面配置&#xff1a; import { defineConfig } from vite import react from vitejs/plugin-react import path from pathexport default defineConfig({plugins: [react()],reso…...

2.13:C语言测试题

21.(b) 6 22.(b) cd 23.b) 5 4 1 3 2 栈&#xff1a;先进后出 24. b,c,d:10,12,120 25.2,5 26.越界访问&#xff0c;可能正常输出&#xff0c;可能段错误 27. 0&#xff0c;41 28. a&#xff09;11 b) 320 29. aab; ba-b; aa-b; 30. p150x801005; p250x810…...

ubuntu22.04 有一台机器说有4T硬盘,但是df的时候看不到,怎么查找

在 Ubuntu 22.04 上&#xff0c;如果你有一块硬盘在使用df命令时未显示&#xff0c;这通常意味着硬盘尚未被挂载或者根本未被分区和格式化。以下是一些步骤来帮助你识别和准备新硬盘&#xff1a; 1. 检查硬盘是否被系统识别 首先&#xff0c;使用lsblk命令来检查系统是否识别…...

【机器学习】数据清洗之识别重复点

&#x1f388;个人主页&#xff1a;甜美的江 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavDestination组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之NavDestination组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、NavDestination组件 作为NavRouter组件的子组件&#xff0c;用于显示导…...

tokio tcp通信

引入crate tokio { version "1.35.1", features ["full"] } 服务端 use std::time::Duration; use tokio::{io::{AsyncBufReadExt, AsyncWriteExt},net::{tcp::{OwnedReadHalf, OwnedWriteHalf},TcpListener, TcpStream,},sync::mpsc, };#[tokio::ma…...

LCR 122. 路径加密【简单】

LCR 122. 路径加密 假定一段路径记作字符串 path&#xff0c;其中以 "." 作为分隔符。现需将路径加密&#xff0c;加密方法为将 path 中的分隔符替换为空格 " "&#xff0c;请返回加密后的字符串。 示例 1&#xff1a; 输入&#xff1a;path "a.ae…...

SpringUtils 工具类,方便在非spring管理环境中获取bean

应用场景&#xff1a; 1 可用在工具类中&#xff0c; 2 spring【Controller,service】环境中&#xff0c; 3 其中的一个方法getAopProxy可获得代理对象&#xff0c;需要将 EnableAspectJAutoProxy(exposeProxy true) 允许获取代理对象 import org.springframework.aop.framew…...

JavaWeb之请求

请求 客户端请求由ServletRequest类型的request对象表示&#xff0c;在HTTP请求场景下&#xff0c;容器提供的请求对象的具体类型为HttpServletRequest HTTP的请求消息分为三部分&#xff1a;请求行、请求头、请求正文。 请求行对应方法 // 获取请求行中的协议名和版本public S…...

VsCode中常用的正则表达式操作

在vscode中可以使用正则表达式来进行搜索内容&#xff0c;极大的方便了我们对大量数据中需要查看的信息进行筛选&#xff0c;使用正则搜索时点击 .* 此文章会持续补充常用的正则操作 1.光标选中搜索到的内容 将搜索的内容进行全选&#xff0c;举例&#xff1a;在如下文件中我需…...

ubuntu22.04@laptop OpenCV Get Started: 007_color_spaces

ubuntu22.04laptop OpenCV Get Started: 007_color_spaces 1. 源由2. 颜色空间2.1 RGB颜色空间2.2 LAB颜色空间2.3 YCrCb颜色空间2.4 HSV颜色空间 3 代码工程结构3.1 C应用Demo3.2 Python应用Demo 4. 重点分析4.1 interactive_color_detect4.2 interactive_color_segment4.3 da…...

mysql 查询性能优化关键点总结

MySQL查询性能优化是数据库管理的重要环节&#xff0c;良好的性能优化可以提高查询效率&#xff0c;降低系统负载。以下是一些关键点&#xff0c;用于优化MySQL查询性能&#xff1a; 1. 索引优化 索引是MySQL查询优化的重要手段&#xff0c;合理的索引可以大大…...

React - 分页插件默认是英文怎么办

英文组件的通用解决方案 这里以分页插件为例&#xff1a; 大家可以看到&#xff0c;最后的这个页面跳转提示文字为Go to&#xff0c;不是中文&#xff0c;而官网里面的案例则是&#xff1a; 解决方案&#xff1a; import { ConfigProvider } from antd; import zhCN from an…...

揭开Markdown的秘籍:引用|代码块|超链接

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Markdown指南、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. ⛳️Markdown 引用1.1 &#x1f514;引用1.2 &#x1f514;嵌套引用1.3 &…...

【C语言】Debian安装并编译内核源码

在Debian 10中安装并编译内核源码的过程如下&#xff1a; 1. 安装依赖包 首先需要确保有足够的权限来安装包。为了编译内核&#xff0c;需要有一些基础的工具和库。 sudo apt update sudo apt upgrade sudo apt install build-essential libncurses-dev bison flex libssl-d…...

使用 C++23 从零实现 RISC-V 模拟器(6):权限支持

本节内容增加了权限表示&#xff0c;设置了三种权限。当 cpu 初始化时默认的权限为 Machine 模式。接下来实现这三种特权模式&#xff0c;随后实现 sret 和 mret 指令。 RISC-V定义了三种特权等级&#xff0c;分别是用户态&#xff08;User Mode&#xff09;、监管态&#xff…...

针对某终端安全自检钓鱼工具的分析

前言 朋友微信找到我&#xff0c;说某微信群利用0day通告进行钓鱼&#xff0c;传播名为“终端安全自检工具”的恶意文件&#xff0c;然后还给了两个IP地址&#xff0c;如下&#xff1a; 咱们就来详细看看这个工具吧。 样本信息 拿到样本&#xff0c;样本的图标&#xff0c;如…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...