范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

JUC(7)JMMampampampVolatile死磕内存模型

  前言
  1、你知道什么是 Java 内存模型 JMM 吗
  2、JMM 与 Volatile 它们两个之间的关系?
  3、JMM 有哪些特性 or 它的三大特性是什么?
  4、为什么要有 JMM,它为什么出现?作用和功能是什么?
  5、happens-before 先行发生原则你有了解过吗?一、JMM 入门1.1 概述
  硬件体系中存在多级的缓存,越往寄存器,则运算速度越快。
  CPU 的运行并不是直接操作内存而是先把内存里边的数据读到缓存,而内存的读和写操作就会造成不一致的问题。
  因为每个人用的操作系统不同,JVM 规范中试图定义一种 Java 内存模型(JMM)来屏蔽各种硬件和操作系统的内存访问差异。以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。所以,我们需要知道 JMM 。
  处理器出来的数据放入高速缓存中。我们可以在主内存和高速缓存中制定一个 缓存一致性协议。1.2 定义作用
  JMM(Java 内存模型 Java Memory Model)本身是一种抽象的概念,并不真实存在。它仅仅描述的是一组约定或规范,通过这组规范定义了程序中(尤其是多线程)各个变量的读写访问方式并决定一个线程对共享变量的写入何时对另外一个线程可见。
  关键技术点都是围绕多线程的原子性、可见性和有序性展开的 。
  能干么呢?
  1、通过 JMM 来实现线程和主内存之间的抽象关系
  2、屏蔽各个硬件平台和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的 内存访问效果。1.3 多线程对变量的读写过程主内存:线程的共享数据区域,主要存储的是 Java 实例对象,所有线程创建的实例对象都存放在主内存中工作内存:每个线程对应一个私有工作内存,主要存储当前方法的所有本地变量信息(共享数据的副本),也可以理解为本地内存
  JMM定义了线程和主内存之间的抽象关系
  ① 线程之间的共享变量存储在主内存中(从硬件角度来说就是内存条)
  ② 每个线程都有一个私有的本地工作内存,本地工作内存中存储了该线程用来读/写共享变量的副本(从硬件角度来说就是CPU的缓存,比如寄存器、L1、L2、L3缓存等)
  ③ 线程对共享变量所有的操作都必须先在线程自己的工作内存中进行后写回主内存,不能直接从主内存中读写(不能越级)
  ④ 不同线程之间也无法直接访问其他线程的工作内存的变量,线程间变量值的传递需要通过主内存来进行(同级不能相互访问)
  总线窥探:
  总线窥探是缓存中的一致性控制器监视或窥探总线事务的一种方案,其目标是在分布式共享内存系统中维护缓存一致性。当主内存的数据被修改后,需要将所有有该数据副本的工作内存的数据变更,这个数据变更通知可以通过总线窥探来完成,所有的窥探者都在监视总线上的每一个事务,如果一个修改共享数据的事务出现在总线上,所有的窥探者都会检查自己的副本是否有相同数据副本,若有则修改。1.4 八种内存交互
  read:作用于主内存,将变量的值从主内存传输到工作内存,主内存到工作内存;load:作用于工作内存,将 read 从主内存传输的变量值放入工作内存变量副本中,即数据加载use:作用于工作内存,将工作内存变量副本的值传递给执行引擎,每当 JVM 遇到需要该变量的字节码指令时会执行该操作。assign:作用于工作内存,将从执行引擎接收到的值赋值给工作内存变量,每当 JVM 遇到一个给变量赋值字节码指令时会执行该操作;store:作用域工作内存,将赋值完毕的工作变量的值写回给主内存;write:作用于主内存,将 store 传输过来的变量值赋值给主内存的变量;
  由于上述6条不能保证多条指令组合的原子性,没有大面积加锁lock:作用于主内存:将一个变量标记为一个线程独占的状态,只是写时候加锁,就只是锁了写变量的过程。unlock:作用于主内存,把一个处于锁定状态的变量释放,然后才能被其他线程占用。二、JMM 三大特性
  并发编程Bug 的源头:可见性、原子性和有序性问题。2.1 可见性2.1.1 案例
  修改变量的值。public class Demo1 {     private  boolean flag =true;     private int count = 0;      public void update(){         flag =false;         System.out.println(Thread.currentThread().getName()+"修改flag");     }     public void load()   {         while (flag){             count++;         }         System.out.println("结束线程,count = "+count);     }      public static void main(String[] args) throws InterruptedException {         Demo1 demo1 = new Demo1();         new Thread(()->{              demo1.load();         },"线程A").start();         // 等待三秒,看另外一个线程修改后,能否进入循环         Thread.sleep(3000);         new Thread(()->{             demo1.update();         },"线程B").start();     } } 复制代码
  控制台输出,线程B修改后,线程 A 无法终止,即无法读取到变量 flag 被其他线程修改了。2.1.2 可见性
  当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道该变更。Java 内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值这种依赖主内存作为传递媒介的方法来实现可见性的。
  JMM 规定了所有的变量都存储在主内存中。
  每个线程都从主内存中读取共享变量的副本,然后修改后提交给主内存,确实像 git。
  系统主内存共享变量数据修改被写入的时机是不确定的,多线程并发下很可能出现 "脏读",所以每个线程都有自己的工作内存,线程自己的工作内存中保存了该线程使用到的变量的主内存副本拷贝。线程间变量值的传递均需要通过主内存来完成。2.1.3 如何保证可见性通过 volatile 关键字保证可见性java 中被 volatile 修饰的变量,在转变汇编指令后会添加一个 lock 前缀,lock 前缀的指令在多核处理器下做两件事:1、将当前处理器缓存行的数据写回系统内存 2、写回内存后,其他cpu缓存了该内存地址的数据无效通过内存屏障保证可见性通过 synchronized 关键字保证可见性加锁线程会获得锁,清空工作内存,从主存拷贝共享变量最新的值到工作内存,源码使用内存屏障实现可见性通过 lock 保证可见性通过 final 关键字保证可见性final 修饰的量不可变
  总结:解决方案可以分为两类:线程上下文切换:让出cpu时间片,线程切换回导致当前线程本地内存失效;内存屏障:jvm 层面的 storeLoad 内存屏障(下节讲解)2.2 有序性
  对于一个线程的执行代码而言,我们总是习惯性认为代码的执行总是从上到下,有序执行。但为了提供性能,编译器和处理器通常会对指令序列进行重新排序。
  指令重排可以保证串行语义一致,但没有义务保证多线程间的语义也一致。即可能产生"脏读",简单说,两行以上不相干的代码在执行的时候有可能先执行的不是第一条,不见得是从上到下的顺序执行,执行顺序会被优化。
  JVM 能根据处理器特性(CPU多级缓存系统、多核处理器等)适当的对机器指令进行重排序,使机器指令能更符合 CPU 的执行特性,最大限度的发挥机器性能。
  单线程环境里面确保程序最终执行结果和代码顺序执行的结果一致。处理器在进行重排序时必须要考虑指令之间的数据依赖性,多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的,结果无法预测。
  在某些情况下可以禁止指令重排。
  如何保证有序性?通过 volatile 关键字保证有序性通过内存屏障保证有序性通过 synchronized 关键字保证有序性通过 Lock 保证有序性2.3 原子性
  指一个操作是不可打断的,即多线程环境下,操作不能被其他线程干扰。例如对于一个静态变量 i =0,线程 A 对它赋值 1,线程 B 对它赋值 -1,那么它要么是 1 要么是 -1,这就是原子性。
  如何保证原子性:通过 synchronized 关键字保证原子性通过Lock保证原子性通过 CAS 保证有序性三、happens-before(多线程先行发生原则)
  在JMM 中,如果一个操作执行的结果需要对另一个操作可见性或者代码重排序,那么这两个操作之间必须存在 happens-before 关系。(逻辑上的先后关系)
  3.1 入门案例
  由这个入门案例可知,第一条语句和第二条语句不能进行排序,否则了能会出现错误。
  happens-before 原则非常重要,它是判断数据是否存在竞争、线程是否安全的主要依据,依靠这个原则,我们解决在并发环境下两操作之间是否可能存在冲突的所有问题。3.2 先行发生原则说明
  如果 Java 内存模型中所有的有序性都仅靠 volatile 和 synchronized 来完成,那么很多操作都将变得非常啰嗦。
  但是我们在编写 Java 并发代码的时候并没有察觉到这一点。
  我们没有时时、处处、次次,添加 Volatile 和 synchronized 来完成程序,这是因为 Java 语言中 JMM 原则下有一个"先行发生"(Happens-Before)的原则限制和规矩,给你定好了规矩。
  这个原则非常重要:它是判断数据是否存在竞争,线程是否安全的非常有用的手段。依赖这个原则,我们可以通过几条简单规则一揽子解决并发环境下两个操作之间是否可能存在冲突的所有问题,而不需要陷入 Java 内存模型苦涩难懂的底层编译原理之中。3.3 总原则(面试答)如果一个操作 happens-before 另一个操作,那么第一个操作的执行结果将对第二个操作 可见 ,而且第一个操作的执行顺序排在第二个操作之前。两个操作之间存在 happens-before 关系,并不意味着一定要按照 happens-before 原则制定的 顺序 来执行。如果重排序之后的执行结果与按照 happens-before 关系来执行的结果一致,那么这种重排序并不非法。3.4 8条3.4.1 次序规则
  一个线程内,按照代码顺序,写在前面的操作先行发生于写在后面的操作;
  前一个操作的结果可以被后续的操作获取。说白了前面一个操作将变量 X 赋值1,那么后面一个操作肯定能知道 X 已经变成 1.3.4.2 锁定规则
  一个unLock操作先行发生于后面((这里的"后面"是指时间上的先后))对同一个锁的lock操作;public class HappenBeforeDemo {     static Object objectLock = new Object();      public static void main(String[] args) throws InterruptedException     {         //对于同一把锁objectLock,threadA一定先unlock同一把锁后B才能获得该锁,   A 先行发生于B         synchronized (objectLock)         {          }     } } 复制代码3.4.3 volatile 变量规则
  对一个volatile变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面的读是可见的,这里的"后面"同样是指时间上的先后。3.4.4 传递规则
  如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;3.4.5 线程启动规则
  Thread对象的start()方法先行发生于此线程的每一个动作3.4.6 线程中断规则
  对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  可以通过Thread.interrupted()检测到是否发生中断,也就是说你要先调用 interrupt()方法设置中断标志位,我才能监测到中断发送。3.4.7 线程终止规则
  线程中的所有操作都先行发生于对此线程的终止检测,我们可以通过Thread::join()方法是否结束、 Thread::isAlive()的返回值等手段检测线程是否已经终止执行。3.4.8 对象终结规则
  一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始对象没有完成初始化之前,是不能调用finalized()方法的3.5 案例分析
  假设存在线程A和B,线程A先(时间上的先后)调用了setValue(1),然后线程B调用了同一个对象的getValue(),那么线程B收到的返回值 是什么?
  我们就这段简单的代码一次分析happens-before的规则(规则5、6、7、8 可以忽略,因为他们和这段代码毫无关系):
  1 由于两个方法是由不同的线程调用,不在同一个线程中,所以肯定不满足程序次序规则;
  2 两个方法都没有使用锁,所以不满足锁定规则;
  3 变量不是用volatile修饰的,所以volatile变量规则不满足;
  4 传递规则肯定不满足;
  所以我们无法通过happens-before原则推导出线程A happens-before线程B,虽然可以确认在时间上线程A优先于线程B指定,但就是无法确认线程B获得的结果是什么,所以这段代码不是线程安全的。那么怎么修复这段代码呢?把getter/setter方法都定义为synchronized方法把value定义为volatile变量,由于setter方法对value的修改不依赖value的原值,满足volatile关键字使用场景3.6 总结
  在Java 语言里面,Happens-Before 的语义本质上是一种可见性。
  A Happens-Before 意味着 A 发生过的事情对 B 来说是可见的,无论 A 事件和 B 事件是否发生在同一个线程里。
  JMM 的设计分为两部分:一部分是面向我们程序员提供的,也就是 happens-before 规则,它通俗易懂的向我们程序员阐述了强内存模型,我们只要理解 happens-before 规则,就可以编写并发安全的程序了.另一部分是针对 JVM 实现的,为了尽可能少的对编译器和处理器做约束从而提高性能,JMM 在不影响程序执行结果的前提下对其不做要求,即允许优化重排序。我们只需要关注前者就好了,也就是理解 happens-before 规则即可,其他繁杂的内容有 JMM 规范结合操作系统给我们搞定,我们只写好代码即可。四、Volatile4.1 Volatile 关键字保证的可见性
  volatile 字面意思是易变的,不稳定的,在 Java 中是个关键字,作为一个类型修饰符,使用方式如下static volatile int i=0; 复制代码
  其目的是告诉我们,该变量是极有可能多变的,不能随意变动目标指令,并保证该变量上操作的原子性。volatile 修饰的变量有可见性,其含义是变量被修改后,应用程序范围内的所有线程都能够直到这个改动volatile 是非排他的,常常用于多线程的共享变量,在一定条件下,它比锁更合适,性能开销比锁更少
  特点:具备可见性、有序性,不具备原子性。
  JMM 下 Volatile 的内存语义是怎样的?当写一个 volatile 变量时,JMM 会把该线程对应的本地内存中的共享变量值立即刷新回到主内存中当读一个 volatile 变量时,JMM 会把该线程对应的本地内存设置为无效,直接从主内存中读取共享变量。所以,volatile 的写内存语义是直接刷新到主内存中,读的内存语义是直接从主内存中读取的。4.2 内存屏障
  volatile 是通过内存屏障保证它的可见性和有序性的。
  那么什么是屏障呢?生活中的例子就是一个栅栏,一个红绿灯通过这个控制人流,不允许我们随意乱窜,从而保证人流车辆的顺序。4.2.1 重排序
  重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段,有时候会改变程序语句的先后顺序。
  例如:int i = 0;               boolean flag = true; i = 1;                //语句1   flag = fasle;          //语句2 复制代码
  语句1和语句2的执行顺序有可能是先 1后2,也可能是先2 后1 ,这样因为它们数据没有依赖性,重排序后的指令绝对不能改变原有的串行语义。
  【注意】:
  ① 如果存在数据依赖关系,例如语句1定义 i=1;语句2定义 i=2,那么就不能重排序。
  ② 在多线程下,对存在控制依赖的操作重排序,可能会改变程序执行结果, 这时候需要内存屏障来保证可见性。
  【拓展】
  重排序的分类和执行流程
  编译器优化的重排序: 编译器在不改变单线程串行语义的前提下,可以重新调整指令的执行顺序
  指令级并行的重排序: 处理器使用指令级并行技术来讲多条指令重叠执行,若不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序
  内存系统的重排序: 由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是乱序执行
  数据依赖性:若两个操作访问同一变量,且这两个操作中有一个为写操作,此时两操作间就存在数据依赖性。4.2.2 内存屏障
  内存屏障,也称内存栅栏,是一类同步屏障指令,是 CPU 或编译器在对内存随机访问的操作中的一个同步点,使得此点之前的所有读写操作都执行后才可以执行此点之后的操作,避免代码重排序。
  内存屏障其实就是一种 JVM 指令,Java 内存模型的重排规则会要求 Java 编译器在生成 JVM 指令时插入特定的内存屏障指令,通过这些内存屏障指令,Volatile 实现了 Java 内存模型中的可见性和有序性
  内存屏障之前的所有写操作都要回到主内存,内存屏障之后的所有读操作都能获得内存屏障之前的所有写操作的最新结果(实现了可见性) 。
  写屏障(Store Memory Barrier):在写指令之后插入写屏障,强制把写缓冲区的数据刷回到主内存中
  读屏障(Load Memory Barrier):在读指令之前插入读屏障,让工作内存当中的缓存数据失效,重新回到主内存中获取最新数据4.2.3 分类
  volatile 变量规则:
  屏障插入策略1、在每个 Volatile 写操作的前面插入一个 StoreStore 屏障禁止前面的普通写和下面的volatile 写重排序2、在每个 Volatile 写操作的后面插入一个 StoreLoad 屏障防止上面的 volatile 写与下面可能有的 volatile 读写重排序
  3、在每一个 Volatile 读操作后面插入一个 LoadLoad 屏障禁止下面的所有普通读操作和上面的 volatile 读重排序4、在每个 volatile 读操作后面插入一个 LoadStore 屏障禁止下面所有的普通写操作和上面的volatile 读重排序
  4.3 volatile 特性4.3.1 保证可见性
  保证不同线程对某个变量完成操作后结果及时可见,即该共享变量一旦改变了就能通知到其他线程获取主内存的值。
  案例:不加 volatile,没有可见性,程序无法停止加了 volatiel,保证可见性,程序可以停止。public class VolatileTest {      static volatile boolean flag =true;     public static void main(String[] args) {         new Thread(()->{             System.out.println("come in");             while (flag){              }             System.out.println("flag to false");         }).start();         try {             Thread.sleep(1000);         } catch (InterruptedException e) {             e.printStackTrace();         }         flag=false;         System.out.println("main flag ="+flag);     } } 复制代码4.3.2 不保证原子性
  对于 volatile 变量具备可见性,JVM 只是保证从主内存加载到线程工作内存的值是最新的,也仅是数据加载时是最新的。但是多线程环境下,"数据计算" 和数据赋值操作可能多次出现,若数据在加载之后,若主内存 volatile 修饰变量发生修改之后,线程工作内存中的操作将会作废去读主内存最新值,操作出现丢失问题。即各个线程私有内存和主内存公共内存中的变量不同步,进而导致数据不一致。
  对于多线程修改主内存共享变量的场景必须使用加锁同步。
  对于 volatile 变量,JVM 只是保证从主内存加载到线程工作内存的值是最新的,也只是数据加载时是最新的。
  如果第二个线程在第一个线程读取旧值和写回新值期间读取 i 的域值,也就造成了线程安全问题。4.3.3 通过禁止指令重排保证有序性
  对于 volatile 修饰的变量的读写操作,都会加入内存屏障。每个 volatile 写操作前面都会加 storeStore 屏障,禁止上面的写与它重排序每个 volatile 写操作后面都会加 StoreLoad 屏障,禁止下面的读与它重排序每个 volatile 读操作后面都会加 LoadLoad 屏障,禁止下面的读与它重排序每个 volatile 读操作后面都会加 LoadStore 屏障,禁止下面的写与它重排序
  4.4 使用场景
  1、单一赋值可以,复合运算不行(i++)volatile boolean flag=false; 复制代码
  2、状态标志,判断业务是否结束/**  *  * 使用:作为一个布尔状态标志,用于指示发生了一个重要的一次性事件,例如完成初始化或任务结束  * 理由:状态标志并不依赖于程序内任何其他状态,且通常只有一种状态转换  * 例子:判断业务是否结束  */ public class UseVolatileDemo {     private volatile static boolean flag = true;      public static void main(String[] args)     {         new Thread(() -> {             while(flag) {                 //do something......             }         },"t1").start();          //暂停几秒钟线程         try { TimeUnit.SECONDS.sleep(2L); } catch (InterruptedException e) { e.printStackTrace(); }          new Thread(() -> {             flag = false;         },"t2").start();     } } 复制代码
  3、开销较低的读、写锁策略
  当读远多于写public class UseVolatileDemo {     /**      * 使用:当读远多于写,结合使用内部锁和 volatile 变量来减少同步的开销      * 理由:利用volatile保证读取操作的可见性;利用synchronized保证复合操作的原子性      */     public class Counter     {         private volatile int value;          public int getValue()         {             return value;   //利用volatile保证读取操作的可见性               }         public synchronized int increment()         {             return value++; //利用synchronized保证复合操作的原子性                }     } } 复制代码
  4、DCL 双端锁的发布
  双重检查锁定public class SafeDoubleCheckSingleton {     private static SafeDoubleCheckSingleton singleton;     //私有化构造方法     private SafeDoubleCheckSingleton(){     }     //双重锁设计     public static SafeDoubleCheckSingleton getInstance(){         if (singleton == null){             //1.多线程并发创建对象时,会通过加锁保证只有一个线程能创建对象             synchronized (SafeDoubleCheckSingleton.class){                 if (singleton == null){                     //隐患:多线程环境下,由于重排序,该对象可能还未完成初始化就被其他线程读取                     singleton = new SafeDoubleCheckSingleton();                 }             }         }         //2.对象创建完毕,执行getInstance()将不需要获取锁,直接返回创建对象         return singleton;     } } 复制代码五、小结
  1、由于 CPU 并非直接操作内存,而是将内存的数据放到高速缓存区中,通过高速缓冲区解决了主内存与 CPU 之间的一个速率读取问题。但因为高速缓存区和主存各有一个数据,带来了缓存不一致问题。
  2、为了解决缓存不一致问题,Java 推出了 JMM 规范,目的是解决由于多线程通过共享内存通信时,产生的主内存和工作内存数据不一致性问题、编译器对代码的重排序等问题。
  3、那么什么是 JMM 规范呢?它是通过一组规则来决定一个线程对共享变量的写入何时对另一个线程可见。它有三大特性:可见性、有序性、原子性。可见性即修改的变量对另一个线程可见,有序性是由于 JVM 会对机器指令进行重排序,多线程下回出现乱序现象原子性是一个线程的操作不能被另一个线程打断
  4、那为了解决这三大问题,是不是我们都要通过加锁或 volatile 等方式解决呢?答案不是的,JMM 给我们提供了 happens-before 原则来辅助我们保证程序的原子性、可见性、有序性问题,它能够判断数据是否存在竞争、线程是否安全的依据。
  5、而 volatile 它能够保证可见性和有序性,它通过内存屏障实现有序性,通过汇编指令后的 lock 前缀,将数据刷新回主存实现可见性,但不能保证原子性。

如何在iPhone上查看总通话时间这篇文章wikishu将教您如何检查您在iPhone上通话的总时间,包括当前的计费周期和手机的生命周期。步骤打开iPhone的设置。通过点击其中一个主屏幕上的灰色齿轮图标来执行此操中山坦洲镇要发展就要抢时间抓机遇拼服务拼经济,镇街行近日,中山市坦洲镇密集召开经济相关会议,不同的会议中却出现了同样一幕主动公布坦洲镇领导和相关部门负责人联系方式,企业家们和政府部门负责人现场互留联系方式。坦洲镇高质量发展大会现场。三球281210布兰纳姆236黄蜂7人上双送马刺14连败直播吧2月16日讯NBA常规赛继续进行,黄蜂主场迎战马刺,黄蜂目前16胜43负排在东部第14位,马刺则是经历了13连败,目前14胜44负排在西部第14位,罗齐尔本场比赛不打。双方上面对ChatGPT这一滔天巨兽,苹果Siri未来还有机会吗?起初,没有人在意这款App。它不过,是一个会聊天的机器人一个能写论文的AI一个可以当搜索引擎的程序直到ChatGPT,和每个人都息息相关一时间,谷歌怕了微软慌了,全世界的科技大厂,马龙搭档陈梦王楚钦再度联手孙颖莎中国乒协将在德班世乒赛前举办两站选拔赛混双竞争最为激烈马龙搭档陈梦王楚钦再度联手孙颖莎随着德班世乒赛日益临近,依照完成巴黎奥运会参赛任务目标着眼洛杉矶奥运会后备年轻队员培养的策略,不满姆总老大队友孤立!梅西罕见摊牌续约暂停,联手内马尔逼宫随着大巴黎在欧冠比赛主场01输给了大巴黎之后,大巴黎在各项赛事也是遭遇到了三连败。球队目前的心态和竞技水准,已经是让大家相当失望了,而球员何尝又不是这样呢。在输给了拜仁的比赛后,内图集国手马龙在京备战德班世乒赛单项赛图为马龙在训练中中国体育讯2月16日,国家乒乓球队队员马龙在国家体育总局训练局备战德班世乒赛单项赛。2023年世乒赛单项赛将于5月20日到28日在南非德班举行。(中国体育图片白宇摄最适合游戏党的手机,还迟疑oppo和小米吗?这4款很优秀如果您喜欢,可以点击上面的关注二字。后续会为您提供更多有价值的内容。今天分享,最适合游戏党的手机,还迟疑oppo和小米吗?这4款很优秀。第一款红米K60E参考价格2599元(122亚洲高科技富豪榜前100名,中国入围的企业家企业实至名归亚洲高科技富豪榜前100名有71位是中国人(含香港台湾),除了宁德时代入围5位,Shein(中国希音电商总部位于南京)入围4位,腾迅入围2位立讯精密入围2位比亚迪入围2位,说明有5星际争霸夺冠有多难?李培楠0。37胜率夺冠,感动无数中国网友近日中国电竞选手李培楠在2023IEM卡托维兹站星际2夺冠的事件可以说引发了不小的热议,相信大家也都有了一个了解,回顾李培楠此次的夺冠历程绝对算得上是一个奇迹,李培楠入围积分倒数,墨西哥跟中国一样有历史韵味的国家墨西哥本身存在很多问题,危险方面可能游客担心最多的就是毒贩和黑帮。但事实上,由于国内媒体过度选择性报道,和美国电影不遗余力的抹黑,这是最不重要可以最后考虑的问题。普遍治安还可以,警
量化自我是焦虑放大器吗?前言之前读虹线的互联网与中国后现代性呓语时,我看到了一种对我们生活中愈发常见现象的解释,非常感兴趣,因此当时说找时间聊聊自己的想法,今天就来填个坑,聊聊对量化自我的一些遐思。1什么新能源产业上市公司图谱总市值破8万亿元,粤苏优势产业差异明显本文来源时代商学院作者陈佳鑫来源时代商学院作者陈佳鑫编辑黄祐芊孙一鸣随着新能源产业爆发式增长,新能源汽车光伏风电成为A股近两年最火热的赛道之一。截至10月末,A股新能源汽车光伏风电完成借壳上市在即复朗集团挑战依旧作为陷入债务危机的金融集团复星旗下奢侈品部门,该公司有望在年底之前完成纽约上市,并计划于2024年实现收支平衡重点复朗集团距离完成SPAC上市又近了一步,其股东定于12月9日对交易政策加持增效明显,北京超九千辆新能源车申请置换补贴新京报讯(记者陈琳)北京市鼓励汽车更新换代政策顺利实施,促进新能源车消费增长效果明显。自今年7月1日开始受理车主补贴申请,至10月31日,汽车置换补贴平台已收到9312辆汽车的补贴新能源冲击下,这5款燃油车或将绝版,想买的珍惜机会伴随着新能源汽车的强势崛起,燃油车面临着前所未有的挑战,表现在市占率和销量层面,其市场份额越来越被新能源汽车蚕食。接下来,我们将要给大家介绍5款或将绝版的燃油车,它们可能是内燃机时新能源里的新赛道,关注这几个分支说起赛道股,可以理解为受政策推动并且吸引大量机构资金的板块。这个名词源于2018年,当时贸易战升级,芯片半导体被制裁,国产替代应运而生,随着大基金一期的投入,半导体板块成为机构扎堆邓苏宁译沙特公司法立法译介邓苏宁对外经济贸易大学外语学院讲师沙特现行的公司法于2016年颁布,取代了1965年的公司法。现行公司法是沙特政府近年来为保持经济可持续发展而出台的几个重点经济法律法规之一,代表了印象最深的一届(中国)世界杯足球助力团2002韩日世界杯是我成为球迷的开始。01年在顺丰做快递,记得有段时间电视,收音机,同事聊天都是一种声音我们出线了街上很多的汽车,商铺都插一把小红旗,完全不懂足球的我,心第144场全马向北马的最后一分钟致敬毫无疑问,艰难的2022年北京马拉松必将载入史册。2022年11月6日,全中国只有一场大型马拉松赛事。如果按照一个月前的赛事排布看,这一天本应有20多场城市马拉松同时开赛。于是,这阿尔维斯入选!巴西队带39岁老将征战世界杯来源环球时报环球时报综合报道巴西队将带着39岁的后卫丹尼尔阿尔维斯参加卡塔尔世界杯,这份26人大名单中,主教练蒂特并没有召入利物浦前锋罗伯托菲尔米诺。ESPN7日称,阿尔维斯拥有4(体育)F1车手汉密尔顿被授予巴西荣誉公民称号新华社里约热内卢11月7日电(记者赵焱陈威华)英国一级方程式(F1)车手刘易斯汉密尔顿7日在巴西国会被授予巴西荣誉公民称号。汉密尔顿在议会的特别仪式上说我无法解释这些年来你们对我的