Java多线程(一):并发编程综述

151 阅读2分钟

什么是并发?

为什么需要并发(并发的好处)?

引入并发编程主要是基于以下考虑:

资源利用率有些情况下,某个程序必须等待其他外部操作执行完毕,才能继续执行这个程序,在这期间CPU被浪费掉,为了提升资源利用率,引入并发,在等待期间,可以让CPU 执行其他程序。

并发带来的问题?

(1)上下文切换

juejin.cn/post/708340…

(2)死锁

死锁是指两个或多个线程(进程),由于竞争资源或者彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法继续下去。 形成死锁的必要条件:

  • 互斥条件。 即一个资源只能被一个进程(线程)占有,直到被该线程释放。
  • 请求与保持。 一个进程因请求被占用资源而发生阻塞时,对已获得资源不释放。
  • 不可剥夺。 线程已获得的资源在使用完之前不能被强行剥夺。
  • 循环等待。 当发生死锁时,所等待的线程必然会形成一条环路。 如何避免线程死锁?
  • 破坏请求与保持条件。超时释放。 可以考虑使用tryLock方法,因为synchronized获取不到就会阻塞,需要手动释放锁。
  • 破坏环路等待条件。 按照某一顺序获取锁,反序释放锁。

(3)线程安全

线程安全是指在多线程运行期间不会产生不符合常规的数据。 要保证线程安全就要保证共享内存的可见性、有序性、原子性

  • 原子性是指一个操作或多个操作,要么全部执行成功,要么全部执行失败。
    • 线程切换会带来原子性问题。
    • 解决方法是synchronized,Lock,原子类。
  • 可见性是指一个线程对共享变量的修改,另外一个线程能立刻看到。
    • 缓存会带来可见性问题
    • 解决方法是synchronized,Lock,volatile
  • 有序性是指程序执行的顺序按照代码的先后顺序执行。
    • 重排序会带来有序性问题
    • 解决方法是Happens-Before原则 参考:《Java并发编程实战》 《Java并发编程的艺术》