【刷题Day30】Python/JAVA - 04(浅)

Python

请解释 Python 代码的执行过程?

Python代码的执行过程主要可以分为以下几个步骤:编译、解释、运行

  • 编译(Compilation)

    当我们运行Python程序时,Python解释器会首先将源代码(.py文件中的代码)转换为字节码。这个字节码是一个中间代码,与平台无关,Python在这里的“编译”不同于传统的编译语言,如C或Java。对于Python来说,这个过程是隐藏的,直接在后台处理。

  • 解释(Interpretation)

    字节码生成后,将由Python虚拟机(PVM,Python Virtual Machine)逐行读取并解释执行。注意,这个过程在CPython中是通过内置的解释器完成的,因此我们也称其为解释执行。

  • 运行(Execution)

    经过解释器逐行解释,最终执行实际的机器指令,处理计算、I/O操作等。

简单来说就是:

源代码 --> 字节码 --> 解释器执行 --> 最终结果

Python 中深拷贝和浅拷贝有什么区别?

  • 深拷贝(deep copy):创建一个新的对象,同时递归地复制所有嵌套的对象。这样即使内部嵌套对象被修改,原对象和复制对象也不会相互影响。
  • 浅拷贝(shallow copy):创建一个新的对象,但不复制内部嵌套的对象。新对象只复制了原对象的引用,因此对任一对象中的改动会影响到另一个对象。

浅拷贝可以通过copy模块的copy()函数或者对象的copy()方法实现,如copy.copy(obj)。深拷贝可以通过copy模块的deepcopy()函数实现,如copy.deepcopy(obj)。

你知道哪些 Python 魔术方法?

在Python中,魔术方法(Magic Methods),也称为双下划线方法(Dunder Methods),是一些以双下划线开头和结尾的方法。这些方法让用户可以定义对象的行为,并在特定的情况下被自动调用。常见的魔术方法包括:

  • __init__:构造函数,在创建对象时调用。
  • __del__:析构函数,在对象被删除时调用。
  • __str__:定义对象的字符串表示,用于print()或str()
  • __repr__:定义对象的官方字符串表示,用于repr()函数
  • __eq__:定义对象相等性比较,处理==运算符
  • __lt__:定义对象小于比较,处理<运算符
  • __add__:定义对象的加法操作,处理+运算符
  • __call__:使对象可以像函数一样被调用
  • __getitem__:定义获取元素的方法,允许使用索引访问。
  • __setitem__:定义设置元素的方法,允许使用索引赋值。

Java

说说 AQS 吧?

AbstractQueuedSynchronizer

简单来说AQS就是起到了一个抽象、封装的作用,将一些排队、入队、加锁、中断等方法提供出来,便于其他相关JUC锁的使用,具体加锁时机、入队时机等都需要实现类自己控制。

它主要通过维护一个共享状态(state)和一个先进先出(FIFO)的等待队列,来管理线程对共享资源的访问。

state用volatile修饰,表示当前资源的状态。例如,在独占锁中,state为0表示未被占用,为1表示已被占用。

当线程尝试获取资源失败时,会被加入到AQS的等待对列中。这个队列是一个变体的CLH队列,采用双向链表结构,节点包含线程的引用、等待状态以及前驱和后继节点的指针。

AQS常见的实现类有ReentrantLock、CountDownLatch、Semaphore等等。

Synchronized 和 ReentrantLock 有什么区别?

Synchronized是Java内置的关键字,实现基本的同步机制,不支持超时,非公平,不可中断,不支持多条件。

ReentrantLock是JUC类库提供的,由JDK1.5引入,支持设置超时时间,可以避免死锁,比较灵活,并且支持公平锁,可中断,支持多条件判断。

ReentrantLock需要手动解锁,而Synchronized不需要,它们都是可重入锁。

一般情况下用Synchronized足矣,比较简单,而ReentrantLock比较灵活,支持的功能比较多,所以复杂的情况用ReentrantLock

性能上,很多年以前Synchronized不如ReentrantLock,现在基本一致

Java 中 volatile 关键字的作用是什么?

主要作用是保证变量的可见性和禁止指令重排优化。

  • 可见性(Visibility):

    volatile关键字确保变量的可见性。当一个线程修改了volatile变量的值,新值会立即被刷新到主内存中,其他线程在读取该变量时可以立即获得最新的值。这样可以避免线程间由于缓存一致性问题导致的“看见”旧值的现象。

  • 禁止指令重排序(Ordering):

    volatile还通过内存屏障来禁止特定情况下的指令重排序,从而保证程序的执行顺序符合预期。对volatile变量的写操作会在其前面插入一个StoreStore屏障,而对volatile变量的读操作则会在其后插入一个LoadLoad屏障。这确保了在多线程环境下,某些代码块执行顺序的可预测性。

你可能感兴趣的:(开发语言,面试题,python,java,开发语言)