初始并发编程之基本知识讲解

本文源自Recently祝祝,创自Recently祝祝。转载请标注出处。

此解决方式在企业中有所应用,适合Java初级开发学习,参考。

本文字数与行数,耐心阅读必有收获。

image.png

1.并发编程说明

1.1并发:

同一个时间段内有多个线程(多线程)在运行,记住是同一个时间段内多个线程都在运行,而不是一个时间段内多个线程同时启动执行,同时执行是并行了,你要明白运行跟执行是不同的,并发的部分是需要进行上下文切换的。所以并发部分需要学习的部分也增加了锁的知识。

image.png

1.2并编程学习路线:

多线程基础核心 → Synchronized实现原理 → Volatile实现原理 → JMM和指令重排→ JUC → 原子类与CAS实现原理 → 锁与AQS实现原理→ 并发工具类→ 并发容器→ 阻塞队列→ 线程池

1.3并发编程

并发编程其实就是利用线程知识编写多线程代码。并且呢在进行并发编程可能会遇到一些线程安全的问题,需要使用到锁,这部分都属于并发编程的领域。或许你说你不了解多线程,但是你肯定用过多线程的工具,例如:Mysql,Redis6.0+等都是多线程应用

2.线程相关知识说明

2.1线程和进程

进程:进行就是一个应用程序。例如:淘宝。 线程:应用程序里的一个部分。例如:淘宝网站里边不同的功能。

线程就是进程的一个最小单元。进程空间独立,线程不是完全独立的,他的堆跟方法区是共享的,线程栈空间和程序计数器是独立的。理论上说线程比进程消耗的资源少。

2.2线程上下文切换

线程上下文切换就是当一个线程运行完一个时间片的时候就分配给其它线程先运行一个时间片,因为系统的分配是随机,所以就有了这个方法,为了防止有的线程运行较慢而导致的后边线程的阻塞。所以就有了程序计数器这一部分。

程序计数器:记录当前线程所执行的字节码指令的行号指示器。就是记录线程运行到了哪一个位置。再次分配到CPU的时候可以定位到执行位置。

要程序计数器的原因一: 4核cpu,逻辑处理核4核有4个处理线程,4个处理核心,可以同一时间点只有有4个线程能被执行,如果一个线程执行的时间很长,不能让他独占cpu,所以才有了线程上下文切换的机制。不能让CPU独占,CPU执行只能执行一个时间片,执行完这个时间片,没有执行完也要进行切换。避免耗时长CPU长期独占CPU。切换的时候就需要记录线程执行到哪里了,这个就由程序计数器来进行记录。

需要程序计数器的原因二:

CPU分配的内核数不固定,可能4个内核只用到了一个内核,操作系统可以把100个线程放在1个核上,也可以放在4个内核上,具有随机性。内核是系统分配的,往往做不到均匀分配。

image.png

2.3线程状态

线程一共存在六种状态:新建、运行、终止、锁阻塞、等待、超时等待。 new(),runnable(),waiting(),blocked(),timed_waiting(),terminated()

image.png

  1. 线程一开始创建就处于新建状态

  2. 之后到达运行状态,其中运行状态包括(运行中与就绪两部分)一开始到达的是就绪状态,获取到时间片之后就到达了运行中状态,

  3. 当线程执行wait方法后进入等待状态(等到其它线程通知方可进入运行状态)

  4. 如果等待状态基础上加上了超时限制的参数,就进入超级等待状态(超时结束进入运行状态)。

  5. 线程执行Synchronized相关部分或者调用wait后被notify了都会进入阻塞状态,这个阻塞也就是锁阻塞。

  6. 线程执行完run()方法,则此线程就终止了。

image.png

2.4wait()和sleep()区别

  • wait()、sleep()都是等待。

  • 但是wait()放开了锁等待,用在线程交互;sleep()是带着锁等待,用在暂停线程。

  • sleep()方法执行完,线程苏醒。wait()需要其它线程唤醒,调用同一个对象的notify和notifyAll。

3.多线程特性

多线程特性:原子性(要不全部执行成功,要么全部失败,不能只执行一半,说的就是个全)、有序性(程序执行有先后,讲究先来后到)、可见性(线程的堆跟方法区是共享的,一个线程修改,其它线程也能看到)

文章全为个人理解,如果发现部分跟你所知道的有出入,欢迎在评论区指出,欢迎探讨。

猜你喜欢

转载自juejin.im/post/7229336438725902395