【安卓报告源码】【视频社交源码下载】【波兰离冰岛源码】list源码原理

2024-12-26 04:29:46 来源:jscharts 源码 分类:娱乐

1.arraylist为什么线程不安全
2.深入理解 Python 虚拟机:列表(list)的源码原理实现原理及源码剖析
3.List LinkedList HashSet HashMap底层原理剖析
4.[stl 源码分析] std::list::size 时间复杂度

list源码原理

arraylist为什么线程不安全

       é¦–先说一下什么是线程不安全:线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。 如图,List接口下面有两个实现,一个是ArrayList,另外一个是vector。 从源码的角度来看,因为Vector的方法前加了,synchronized 关键字,也就是同步的意思,sun公司希望Vector是线程安全的,而希望arraylist是高效的,缺点就是另外的优点。 说下原理(百度的,很好理解): 一个 ArrayList ,在添加一个元素的时候,它可能会有两步来完成:

       1. 在 Items[Size] 的位置存放此元素;

       2. 增大 Size 的值。

       åœ¨å•çº¿ç¨‹è¿è¡Œçš„情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;

       è€Œå¦‚果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。

       é‚£å¥½ï¼ŒçŽ°åœ¨æˆ‘们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。

       ç¤ºä¾‹ç¨‹åºï¼š

       package test;

       import java.util.ArrayList;

       import java.util.List;

       public class ArrayListInThread implements Runnable {

       List<String> list1 = new ArrayList<String>();// not thread safe

       // List<String> list1 = Collections.synchronizedList(new ArrayList<String>());// thread safe

       public void run() {

       try {

       Thread.sleep((int)(Math.random() * 2));

       }

       catch (InterruptedException e) {

       e.printStackTrace();

       }

       list1.add(Thread.currentThread().getName());

       }

       public static void main(String[] args) throws InterruptedException {

       ThreadGroup group = new ThreadGroup("mygroup");

       ArrayListInThread t = new ArrayListInThread();

       for (int i = 0; i < ; i++) {

       Thread th = new Thread(group, t, String.valueOf(i));

       th.start();

       }

       while (group.activeCount() > 0) {

       Thread.sleep();

       }

       System.out.println();

       System.out.println(t.list1.size()); // it should be if thread safe collection is used.

       }

       }

深入理解 Python 虚拟机:列表(list)的实现原理及源码剖析

       深入理解 Python 虚拟机:列表(list)的实现原理及源码剖析

       在 Python 虚拟机中,列表作为基本数据类型之一,源码原理能够存储各种类型的源码原理数据并支持多种操作。本文将详细解析列表在 cpython 实现中的源码原理结构和关键操作的源代码。

       列表结构解析

       在 cpython 实现中,源码原理列表由一系列元素构成,源码原理安卓报告源码每个元素由一个指针指向 Python 对象。源码原理列表还包含一个表示元素数量的源码原理字段,一个用于存储列表长度的源码原理字段,以及一个用于存储对象引用计数的源码原理字段。

       创建和扩容机制

       创建列表时,源码原理不会直接分配内存,源码原理而是源码原理将需要释放的内存地址保存在数组中,以便下次创建列表时复用。源码原理视频社交源码下载列表扩容时,源码原理通过检查当前容量并相应地增加,以适应新添加的元素。

       插入和删除操作

       插入元素时,将插入位置及其后元素后移一位。删除元素时,将后续元素前移,直至空位。

       复制操作

       列表复制分为浅拷贝和深拷贝。浅拷贝仅复制对象的指针,改变原始列表中的元素会影响复制后的列表。深拷贝则复制对象及其内部内容,确保复制后的波兰离冰岛源码列表独立于原始列表。

       列表清理和反转

       清空列表时,将元素数量字段设置为零,并减少所有对象的引用计数,以便在计数为零时自动释放内存。反转列表使用交换元素指针实现,不改变元素值。

       总结

       本文深入介绍了 Python 列表的内部实现,包括创建、扩容、插入、删除、复制、清理和反转等操作的迷你梦幻游戏源码源代码。理解这些细节有助于更高效地编写 Python 代码并深入掌握 Python 的内部机制。

List LinkedList HashSet HashMap底层原理剖析

       ArrayList底层数据结构采用数组。数组在Java中连续存储,因此查询速度快,时间复杂度为O(1),插入数据时可能会慢,特别是需要移动位置时,时间复杂度为O(N),但末尾插入时时间复杂度为O(1)。数组需要固定长度,ArrayList默认长度为,最大长度为Integer.MAX_VALUE。在添加元素时,循环呼叫源码app如果数组长度不足,则会进行扩容。JDK采用复制扩容法,通过增加数组容量来提升性能。若数组较大且知道所需存储数据量,可设置数组长度,或者指定最小长度。例如,设置最小长度时,扩容长度变为原有容量的1.5倍,从增加到。

       LinkedList底层采用双向列表结构。链表存储为物理独立存储,因此插入操作的时间复杂度为O(1),且无需扩容,也不涉及位置挪移。然而,查询操作的时间复杂度为O(N)。LinkedList的add和remove方法中,add默认添加到列表末尾,无需移动元素,相对更高效。而remove方法默认移除第一个元素,移除指定元素时则需要遍历查找,但与ArrayList相比,无需执行位置挪移。

       HashSet底层基于HashMap。HashMap在Java 1.7版本之前采用数组和链表结构,自1.8版本起,则采用数组、链表与红黑树的组合结构。在Java 1.7之前,链表使用头插法,但在高并发环境下可能会导致链表死循环。从Java 1.8开始,链表采用尾插法。在创建HashSet时,通常会设置一个默认的负载因子(默认值为0.),当数组的使用率达到总长度的%时,会进行数组扩容。HashMap的put方法和get方法的源码流程及详细逻辑可能较为复杂,涉及哈希算法、负载因子、扩容机制等核心概念。

[stl 源码分析] std::list::size 时间复杂度

       在对Linux上C++项目进行性能压测时,一个意外的发现是std::list::size方法的时间复杂度并非预期的高效。原来,这个接口在较低版本的g++(如4.8.2)中是通过循环遍历整个列表来计算大小的,这导致了明显的性能瓶颈。@NagiS的提示揭示了这个问题可能与g++版本有关。

       在功能测试阶段,CPU负载始终居高不下,通过火焰图分析,std::list::size的调用占据了大部分执行时间。火焰图的使用帮助我们深入了解了这一问题。

       查阅相关测试源码(源自cplusplus.com),在较低版本的g++中,std::list通过逐个节点遍历来获取列表长度,这种操作无疑增加了时间复杂度。然而,对于更新的g++版本(如9),如_glibcxx_USE_CXX_ABI宏启用后,list的实现进行了优化。它不再依赖遍历,而是利用成员变量_M_size直接存储列表大小,从而将获取大小的时间复杂度提升到了[公式],显著提高了性能。具体实现细节可在github上找到,如在/usr/include/c++/9/bits/目录下的代码。

本文地址:http://581.net.cn/html/39a267697284.html 欢迎转发