zoukankan      html  css  js  c++  java
  • Java 多线程

    多线程


    资源:url

    线程与进程

    进程:运行中的程序,属于操作系统级别的

    • 1.进程是资源分配的基本单位
    • 2.进程中包含多个线程,线程共享进程资源
    • 3.线程是处理器调度的基本单位

    线程状态

    线程的状态有7种,如下

    当启动一个线程就会进入就绪状态(ready-to-run),当线程获取到了CPU资源即开始执行,此算为获取CPU资源可能会存在多个线程竞争CPU资源的情况,谁抢到了谁就执行

    多线程的问题

    分析多线程问题时可以使用Java JDK自带的工具来分析class字节码文件
    命令:javap -verbose *.class
    命令会将字节码文件翻译成Java的代码指令

    安全性问题

    安全性是多线程最核心的问题
    在多线程中,线程之间的执行顺序是难以确定的,所以有限单线程的问题,在多线程中可能就会出现奇诡的现象。那么多线程的安全性就是线程能够按照预期执行出正确的结果
    线程安全性问题的关键在于:多个线程会同时请求相同的资源,如果没有做安全操作比如synchronized或者加锁,那么当多个线程在获得CPU时间片进行操作时,操作的指令和结果在栈中,而数据在局部变量池中是在堆中,操作完了结果还没有写入堆,那么就会出现冲突,数据都还在各自的操作栈中

    什么情况下会出现线程安全问题

    • 1.多线程环境
    • 2.多线程之间共享资源
    • 3.对资源进行非原子性操作(什么是原子性操作,命令不可分割即操作只有一条指令一个字节码指令,比如写就不是原子性的,先num=num++会读比如指令iconst_,然后写比如指令iadd,最后存比如指令putfield)

    线程安全性的解决办法

    活跃性问题

    活跃性问题有三种:

    • 死锁
    • 饥饿与公平
    • 性能

    死锁

    即多个线程相互占用资源谁都不释放导致线程都无法执行

    饥饿

    • 高优先级的线程吞噬所有低优先级线程的CPU时间片导致,低优先级的线程一直无法被执行
    • 线程被永久堵塞在一个等待进入同步块的状态
    • 等待线程永远不被唤醒
    如何尽量避免饥饿的方法
    • 设置合理的优先级(设置优先级时尽可能使用Thread.MIN_PRIORITY参数而不是直接写数字,这样能避免不同平台具体优先级数量大小的差异)
    • 使用锁来代替synchronizaed(因为synchronized是看CPU的时间片,基本看天,而锁则可以自己去更好的控制)

    活锁

    即多个线程相互礼让资源却导致谁都没有被执行

    多线程编程

    任何对象都可以作为锁,那么锁信息又存在在对象的什么地方呢?

    答案是:存在在对象头中
    对象头中的信息:
    1.Mark Word --->保存了锁信息,当然Mark Word内容不止锁信息
    2.Class Metadata Address-->指向对象的类型地址
    3.Array Length 数组对象还会保存数组长度信息

    轻量级锁

    多个线程可以同时进入同步代码块,即多个线程能够同时获取锁。线程进入后会自旋(就是while(true))不断地请求以获取执行锁,其实这步也是会耗费CPU资源的

    偏向锁

    每次获取锁和释放锁会浪费资源,但很多情况下,竞争锁不是由多个线程,而是由一个线程在使用。mark word会记录很多信息(线程id,Epoch,是否是偏行锁,锁标志位),偏行锁就是每次使用完之后不会像一般锁会立即释放锁,而是等待竞争出现,就是有别的线程在竞争时才会释放。也就是当执行完后不释放锁,再次进入时如果还是同一个线程就继续执行,不用去获得锁,只有当别的线程执行竞争锁,偏向锁才会去释放锁。
    偏向锁的使用场景:这样当只有单线程在访问同步代码块

    重量级锁

    当一个锁进入后,其他的锁必须等待,synchronized就是重量级锁

    重入锁

    重入锁:比如有两个锁(两个synchronized块)当同一个线程拿到第一个锁的方法调用第二个方法时也可访问,而不是有了第一把锁就不能再次获得第二个方法的锁

    synchronized

    synchronized就是内置锁也是重入锁,内置锁即所有的对象都可以作为锁,而每个对象的内置锁都是互斥的,即只能有一个对象拿到锁,其他没有锁的对象就都不能访问。

    当synchronized修饰普通方法时,内置锁就是当期的实例
    当synchronized修饰静态方法时,内置锁就是当前的Class字节码对象
    当synchronized修饰块时,内置锁就是指定的synchronized(object)指定的对象

    Volatile

    笔记连接

    本博客为Swagger-Ranger的笔记分享,文中源码地址: https://github.com/Swagger-Ranger
    欢迎交流指正,如有侵权请联系作者确认删除: liufei32@outlook.com

  • 相关阅读:
    Linux7运维视频教程
    大型C++网络游戏开发视频教程
    Hadoop实战视频教程下载
    Greenplum分布式数据库开发入门到精通
    Greenplum Hadoop视频教程_Hadoop应用案例剖析
    Linux7企业级运维高端培训视频教程
    咯咯咯
    第五周作业
    数组
    2019年春季学期第三周作业
  • 原文地址:https://www.cnblogs.com/Swagger-Ranger/p/10669894.html
Copyright © 2011-2022 走看看