什么是多线程并发编程
# 什么是多线程并发编程
# 了解什么是并发,什么是并行?
并发:一段时间内,执行多个没有结束的任务。 并行:单位时间内,同时执行多个任务。
注意:并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行
而在多线程编程实践中,线程的个数往往多于CPU的个数,所以一般都称多线程并发编程而不是多线程并行编程。
# 内存可见性问题
首先看下java的内存模型,可以更好了解问题 每个线程都有自己的工作内存和缓存(一级缓存),主内存保存存着共享变量,CPU还提供一个共享的二级缓存,如果二级缓存有对应数据,线程会优先取二级缓存获取或刷入
接下来说一个例子,演示为什么会有内存可见性的问题
假设现在有一个双核cpu服务器,首先thread1 获取x的值,这时候只有共享的主内存有值,二级缓存和thread1的私有内存和一级缓存都没有x的值,因此thread1会直接去主内存获取值。
thread1会直接从主内存,将x=0写入两级缓存,写入私有内存,然后再将x的值修改为1,最后再将x=1刷到两级缓存,和主内存中。
这时候来了个thread2,也准备修改x的值,开始时它的私有内存和一级缓存也是空的,但是主内存和二级缓存的x值为1,所以thread2会优先获取二级缓存中的值
thread2获取二级缓存x=1,写入自己的一级缓存和私有内存,然后将x修改为2,私有内存和一级缓存都修改为2,x=2也刷入二级缓存和主内存,到这里都没有问题。
这时thread1又想将x的值修改为3,thread1看自己的一级缓存有x的值,就不会去二级缓存获取,这样就造成了读取的数据和主内存上的不一致
# 解决内存可见性的方法
# synchronized 关键字
# synchronized关键字介绍
Synchronized关键字是Java中用于实现线程同步的重要特性之一。它可以应用于方法或代码块,用于确保在多线程环境下对共享资源的安全访问。
- 修饰静态代码块
- 修饰属性变量
- 修饰属性方法
使用synchronized关键字,当线程拿到类或对象的监视器锁,会具有排他性,就是其他线程不能抢占该资源,直到线程释放锁(释放锁的时机有正常执行完和被打断)
# synchronized内存语义
当被synchronized修饰的方法被执行时: 线程进入方法,线程读取的变量会从工作内存清除,从而去读取主内存的变量值 线程退出方法,会将线程修改的值刷回到主内存
# volatile 关键字
被volatile修饰的变量,被读取时不会去工作内存读取,而是直接去主内存读取,写入变量值时,将工作内存的变量值写回主内存。 可以防止指令重排。
原子性,可见性,有序性 是如何实现的