之前对多线程这块一直不是很懂,现在看了一端时间的书与资料,写一些自己的心得体会吧
- 并发与并行
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
打个比方:并行就是一个乐队在同一时间一起演奏 , 并发 就是一个人很短的时间内又弹钢琴又打鼓,只不过是他速度很快,感觉有多个人在演奏而已;
- 线程与进程
进程:运行中的应用程序称为进程,拥有系统资源(cpu、内存)
线程:进程中的一段代码,一个进程中可以有多段代码。本身不拥有资源(共享所在进程的资源),线程是最小的执行单元,每个进程都至少拥有一个线程;
在java应用程序来说,一个web 服务就是一个进程,在linux 系统中,当程序开启时,我们需要手动 或自动的给它分配内存空间,是因为它其中的线程需要这些(程序计数器,堆区,栈区等等)才能跑起来。
关闭时,我们可以通过对应的命令来关闭它,那它所拥有的系统资源就会释放,它的线程也会停止。
举个栗子
公司=进程 ,码农=线程;
在公司中,我们敲代码需要公司提供办公地点工具(电脑,座位,工资等等),我们共享这些资源当谁需要时给谁使用,当公司倒闭时会将这些回收,我们码农没有作案工具自然就没有办法运作下去。
- 线程的生命周期
- 多线程
上面我们大致了解线程,接下来我们看看如何启动多个线程
创建线程的方式有三种:
1.继承Thread类 (不符合里氏代换原则)
2.实现Runnable 接口 相对于第一种推荐第二种
3.实现Callable接口,它有两个特点 一是可以通过call()获取返回值,二是call()方法可以抛出异常;
- 什么情况下会有线程安全问题?
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
解决方案一般来说有四种;
1.数据单线程内可见
单线程是安全的,通过限制数据仅在单线程内可见,可以避免数据被其他线程篡改。最典型的就是线程局部变量,存储在独立虚拟机栈帧的局部变量表中,与其他线程没有关系。比如 ThreadLocal (要是感兴趣我会专门写一篇这个)
2.只读对象
只读对象是安全的,他的特性是允许复制,拒绝写入。只读对象需要使用private final修饰 避免继承及属性被中途修改,没有任何更新方法,返回值不能为可变对象;
3.线程安全类
比如StringBuffer 就是线程安全类,采用synchronized 关键字来修饰相关方法
4.同步与锁机制
需要自己在代码中实现, 通过加锁或同步代码块的方法等等
其实综上所述, 线程安全 要么只读 要么加锁。 在JDK中有提供对应的并发包 可以帮助我们实现(要是感兴趣我也会专门写一篇这个)
之前我朋友在面试时,被一个问题问倒了 ,单例模式是否线程安全? 这里篇幅有限就不在一一说明了,感兴趣的同学可以去看看,感觉这个写的还可以(https://www.cnblogs.com/sunnyDream/p/8011186.html)
有讲到 双重锁 和volatile关键字。(volatile关键字可以禁止指令重排序)
图片及部分资料网上所得
来源:https://blog.csdn.net/weixin_43588981/article/details/100124041