多线程之概念字典

来源:互联网 发布:java上传文件的原理 编辑:程序博客网 时间:2024/05/22 05:13

本文主要对多线程开发中的一些数据字典进行归纳总结,设计到线程同步、并行、并发、线程状态等概念。

一、并行 VS 并发

  • 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时;
  • 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力;

并发VS并行

二、同步

同步:从英文synchronize(使同时发生)翻译过来的,然而,线程同步的真实意思和字面意思恰好相反。线程同步的真实意思其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。

关于线程同步,需要牢牢记住以下几点:

  • 线程同步就是线程排队,线程同步的目的就是避免线程“同步”执行
  • 只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要;
  • 只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步;
  • 多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步;

三、线程安全

线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果,如不加事务的转账代码;

四、线程状态

状态:
线程状态
状态转换图:
状态转换

阻塞(Blocked):线程在运行的过程中,因某些原因而停止运行进入等待的状态;

阻塞线程特性:放弃CPU,暂停运行,只有导致阻塞的原因消除,才能恢复运行,或者被其他线程中断,该线程退出阻塞状态,并抛出InterruptedException异常;

线程在Running的过程中可能会进入阻塞(Blocked)状态的情况:

  • 调用join()和sleep()方法,sleep()时间结束或被打断,join()中断都会回到Runnable状态,等待JVM的调度;
  • 线程执行I/O操作,等待相关资源进入Blocked状态,I/O完成,会回到Runnable状态,等待JVM的调度;
  • 调用wait(),使该线程处于等待池(wait blocked pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool ),释放同步锁使线程回到可运行状态(Runnable);
    -Running状态的线程调用Synchronized代码,或说对Running状态的线程加同步锁(Synchronized),使其进入(lock blocked pool ),同步锁被释放进入可运行状态(Runnable);

此外,在runnable状态的线程是处于被调度的线程,此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。

五、死锁

死锁:在并发环境下,当两个或多个线程在执行的过程中,因争夺资源而相互等待,且若无外力的作用,将永远无法推进下去的一种现象;

死锁的四个条件:

  • 互斥(mutual exclusion):资源在某个时刻只能被被一个线程使用;
  • 持有(Hold and Wait):当请求的资源已被占用从而导致线程阻塞时,资源占用者不但无需释放该资源,反而可以请求更多资源;
  • 不可剥夺(No preemtion):线程获取的资源不可被强行剥夺,即只有资源占有者才能释放资源;
  • 环形等待:若干线程以不同次序获取资源,从而形成环形等待的局面;

避免死锁:主要破坏2/3/4条件

  • 上锁操作事物化,事物可回退;同时通过锁管理器检测死锁,并剥夺资源;
  • 控制加锁顺序,防止环形等待;

参考

  1. Java中的多线程你只要看这一篇就够了
  2. 在JAVA中线程到底起到什么作用!
原创粉丝点击