java学习笔记(第11天)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ARPOSPF/article/details/79464066

成员变量和局部变量的区别:

  1. 作用域不同:局部变量的作用域仅限于定义它的方法;成员变量的作用域在这个类内部都是可见的;
  2. 初始值不同:java会给成员变量一个初始值,java不会给局部变量赋予初始值;
  3. 在同一个方法中,不允许有同名局部变量;在不同的方法中,可以有同名局部变量;
  4. 两类变量同名时,局部变量具有更高的优先级。

构造方法:

  1. 使用new+构造方法 创建一个新的对象
  2. 构造方法是定义在Java类中的一个用来初始化对象的方法,构造方法与类同名且没有返回值
  3. 当没有指定构造方法时,系统会自动添加无参的构造方法
  4. 当有指定构造方法,无论是有参、无参的构造方法都不会自动添加无参的构造方法
  5. 构造方法的重载:方法名相同,但参数不同的多个方法,调用时自动根据不同的参数选择相应的方法
  6. 构造方法不但可以给对象的属性赋值,还可以保证给对象的属性赋一个合理的值

测量上下文切换次数和时长:

  1. 使用Lmbench3可以测量上下文切换的时长
  2. 使用vmstat可以测量上下文 切换的次数

如何减少上下文切换

  1. 减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。(协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。)
  2. 避免死锁的几个常见方法:
      • 避免一个线程同时获取多个锁。
      • 避免一个线程在锁内同时占用多个资源,尽量避免每个锁只占用一个资源。
      • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。
      • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

资源限制的挑战:

  1. 什么是资源限制?资源限制是指在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。软件资源限制有数据库的连接数和socket连接数等。
  2. 资源限制引发的问题:增加了上下文切换和资源调度的时间。
  3. 如何解决资源限制的问题?对于硬件资源限制,使用集群并发执行程序,对于软件资源限制,考虑使用资源池将资源复用。
  4. 在资源限制情况下进行并发编程?根据不同的资源限制调整程序的并发度。

在多线程并发编程中synchronized和volatile都扮演着重要的角色。volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。如何volatile变量的修饰符使用恰当的话,它比synchronized的使用和执行成本更低,因为它不会引起线程上下文的切换和调度。

volatile的两条实现原则:1)Lock前缀指令会引起处理器缓存回写到内存。2)一个处理器的缓存回写到内存会导致其他处理器的缓存无效。

在使用volatile变量时,用一种追加字节的方式来优化队列出队和入队的性能。

synchronized实现同步的基础:Java中的每一个对象都可以作为锁,具体表现为以下三种形式:

  1. 对于普通同步方法,锁是当前实例对象。
  2. 对于静态同步方法,锁是当前类的Class对象
  3. 对于同步方法块,锁是Synchonized括号里配置的对象。

当一个线程试图访问同步代码块,它首先必须得到锁、退出或抛出异常时必须释放锁,JVM基于进入和退出Moniter对象来实现方法同步和代码块同步,但两者的实现细节不一样。代码块同步是使用monitorenter和monitorexit指令实现的,而方法同步是使用另外一种方式实现的。monitorenter指令是在编译后插入到同步代码块的开始位置,而monitorexit是插入到方法结束处和异常处,JVM要保证monitorenter必须由对应的monitorexit与之匹配。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获取对象的锁。

synchronize用的锁是存在java对象头里的。在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。

锁可以升级但不能降级,意味着偏向锁升级成轻量级锁后不能降级成偏向锁。目的是提高获得锁和释放锁的效率。

在大多数情况下,锁不均不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需简单地测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。如果测试成功,表示线程已经获得了锁,如果测试失败,则需要再测试一下Mark Word中偏向锁的标识是否设置为1(表示当前是偏向锁);如果没有设置,则使用CAS竞争锁,如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程。

(1)偏向锁的撤销,偏向锁使用了一种等到竞争出现才释放锁的机制,所以当其他线程尝试竞争偏向锁时持有偏向锁的现场才会释放锁。

(2)程序默认会进入轻量级锁状态。

猜你喜欢

转载自blog.csdn.net/ARPOSPF/article/details/79464066