jvm是java虚拟机吧,java实现jvm

  jvm是java虚拟机吧,java实现jvm

  如何解决写爬虫IP受阻的问题?立即使用。

  内存模型

  内存模型是在特定操作协议下对特定内存或缓存进行读写访问的过程抽象。它的主要目标是定义程序中每个变量的访问规则。

  主内存和工作内存

  

  的所有变量都存储在主内存中,每个线程都有自己的工作内存。它的工作内存是线程使用的变量的主内存的副本。线程必须读取并分配工作内存中的变量,而不是直接读取主内存中的变量。

  内存间交互操作

  从主内存复制到工作内存:读取和加载操作是顺序执行的。

  与主内存同步的内存:存储和写操作。

  volatile的特性

  Volatile的功能和synchronized一样,但是比synchronized轻。其特点主要包括以下两点:

  保证此变量对所有线程的可见性

  你什么意思?当一个线程修改这个变量的值时,其他线程会立即知道这个新值。普通变量做不到这一点,普通变量的值需要通过主存在线程间传递。比如线程A修改了一个普通变量的值然后写回主存,而另一个线程B在线程A写回之后从主存中读取,新的变量值会被线程B看到。

  禁止指令重排序优化

  因为指令重排序会干扰程序的并发执行。

  多线程

  

  为什么需要多线程?

  计算机的运算速度与其存储和通信子系统的运算速度相差太大,大量时间花在磁盘I/O、网络通信和数据库访问上。使用多线程可以更好的利用cpu。

  

  有哪些并发应用场景?

  充分利用计算机处理器

  一台服务器同时向多个客户端提供服务。

  

  如何使处理器内部的运算单元被充分利用?

  加入一层高速缓存

  将操作所需的数据复制到缓存中,以便快速执行操作。当操作完成时,它会从缓存同步回内存,这样处理器就不必等待缓慢的内存读写。但是,有一个问题需要考虑:如何保证缓存的一致性。

  对输入代码进行乱序执行优化

  线程的实现方式

  使用内核线程实现

  内核是由操作系统的内核直接支持的线程。

  使用用户线程实现

  用户线程的建立、同步、销毁和调度完全在用户状态下完成,不需要内核的帮助,内核无法感知线程存在的实现。这种实现很少使用。

  使用用户线程加轻量级进行混合实现

  融合在一起。

  线程调度

  线程调度是指系统将处理器使用权分配给线程的过程。主要有两种:合作型和抢先型。

  协同式

  线程的执行时间是由线程本身控制的。当一个线程完成自己的工作时,它会主动通知系统切换到另一个线程。

  其优点是实现简单,没有线程同步的问题。缺点是如果一个线程写的有问题,系统没有被告知一直切换线程,程序就会一直被堵在那里,容易导致系统崩溃。

  抢占式

  线程会被系统分配执行时间,线程切换不是自己决定的。这是java使用的线程调度方法。

  线程安全

  当多个线程访问一个对象时,如果通过调用该对象可以获得正确的结果,而无需考虑线程在运行时环境中的调度和交替执行,并且无需对调用方进行额外的同步或任何其他协调操作,则该对象是安全的。

  共享数据的分类

  不可变

  不可变共享数据是用final修饰的数据,它必须是线程安全的。如果共享数据是一个基本类型变量,那么在定义它时只需要使用final关键字。

  如果共享的数据是一个对象,要求对象的行为不会影响其状态,并且对象中所有带状态的变量都可以声明为final。例如,String类是一个不可变的类。

  绝对线程安全

  在Java API中把自己标记为线程安全类,大部分都不是绝对线程安全的。例如,Vector是一个线程安全的集合,它的所有方法都被修饰为同步的,但在多线程环境中,它仍然不是同步的。

  相对线程安全

  相对线程安全就是我们通常所说的线程安全。它只能保证这个对象的单个操作是线程安全的。但是,对于某些按特定顺序的连续调用,可能需要在调用方使用额外的同步方法来确保调用的正确性。

  大多数线程安全类都属于这种类型。

  线程兼容

  对象本身不是线性安全的,但是通过在调用方正确使用同步,可以在并发环境中安全地使用它。大多数非线程安全的类都属于这种类型。

  线程对立

  在任何情况下,它都不能在多线程环境中并发使用,如System.setIn()和System。SetOut()。一个修改输入,一个修改输出,两者不能“交替”。

  实现方法

  方式一:互斥同步——悲观并发策略

  (1)同步

  原理是:这个关键字编译后,会在同步块前后形成两个字段代码指令monitorenter和monitorexit。当执行monitorenter命令时,程序将尝试获取对象的锁。如果可以获取,锁定计数器将被设置为1。相应地,当monitorexit命令被执行时,锁计数器将被设置为-1。当计数器为0时,锁被释放。

  其特征在于对于同一线程是可重入的;在已经进入的线程完成执行之前,同步块将阻止其他线程的进入。

  选择场景是:只有在真正需要的时候才使用这个,因为它是重量级的。

  (2)重入锁

  这个可重入锁是java.util.concurrent(JUC)包下的一个类。它的高级特性是:等待可以中断,可以实现公平锁,锁可以绑定多个条件。

  方式二:非阻塞同步——乐观并发策略

  先做手术。如果没有其他线程争用共享数据,则操作成功。如果共享数据出现争用和冲突,那么就采取其他补偿措施。

  方式三:无同步方案

  如果一个方法不涉及共享数据,就不需要同步。例如可重复代码和线程本地存储。

  (1)可重入代码

  如果一个方法的返回结果是可预测的,只要输入相同的数据,它都可以返回相同的结果,那么它就可以满足可重入的要求。

  (2)线程本地存储

  如果一段代码中需要的数据必须和其他代码共享,而这些共享的数据代码是在同一个线程中执行的,那么我们可以把共享数据的可见范围限制在一个线程内,这样就保证了在没有同步的情况下线程之间不会发生数据争用。

  锁优化

  适应性自旋

  因为阻塞或唤醒JAVA线程需要操作系统切换CPU状态,这种状态转换需要处理器时间。如果同步代码块中的内容过于简单,状态转换很可能会比用户代码的执行时间更长。

  为了解决这个问题,我们可以让请求锁的线程“等一会儿”,执行一个繁忙的循环并旋转。此时,处理器的执行时间没有被放弃。如果自旋超过了限定的次数,仍然没有成功获取锁,那么线程将以传统的方式挂起。

  那什么叫做适应性自旋呢?

  即在同一个锁对象上,如果spin wait刚刚成功获得锁,虚拟机会认为这个spin获得锁的概率相当高,会允许其spin wait持续相对更长的时间。相反,如果旋转很少成功获得锁,则可以省略旋转过程。

  

  锁消除

  当虚拟机实时编译器运行时,它消除了一些代码中需要同步的锁,但检测到没有共享数据竞争的可能性。

  锁粗化

  如果一系列连续的操作重复锁定和解锁同一个对象,即使锁定操作发生在循环中,频繁的互斥同步操作即使没有线程竞争也会导致不必要的性能损失。

  如果虚拟机检测到一系列的零碎操作锁定了同一个对象,就会把锁定同步的范围粗化到整个操作序列之外,这样只需要一次锁定就够了。

  轻量级锁

  在不存在多线程竞争的前提下,减少了传统重量级锁使用操作系统互斥体带来的性能损失。

  适用场景:无实际竞争,多线程交替使用锁;允许短锁争用。

  偏向锁

  当没有竞争且只有一个线程使用锁时,锁偏向用于减少使用轻量级锁的性能消耗。轻量级锁每次申请和释放锁至少需要一个ca,而偏置锁初始化时只需要一个ca。

  适用场景:没有实际竞争,以后只有第一个申请锁的线程会使用锁。

  以上是JAVA虚拟机中高效并发的详细介绍。更多相关问题请访问PHP中文网:JAVA视频教程。以上是JAVA虚拟机(JVM)的详细介绍(八)。3354高效并发的细节。请多关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: