一、引言
线程的问题本质上就是并发的问题,并发问题的根源是CPU的运行速度、内存速度、IO、网络资源请求的速度处于不同的层次,相差很多。
进程是资源分配的单位,线程是处理器调度的最小单位,同一进程下面的线程共享系统分配给该进程的资源
二、内存一致性
Java内存模型
多处理器系统的CPU和内存、高速缓存(缓存一致性问题)模型
Java内存模型就是参考该模型的:
java线程(n)——》工作内存(n)——》主内存(1),同样为了解决缓存一致性的问题,
即一个变量如何从内存拷贝到工作内存,又如何从工作内存的同步到主内存。
内存交互操作
Java内存模型定义了八种原子操作,来实现主内存和工作内存之间的同步。
volatile的理解
Java内存模型对volatile专门定义了一些特殊的访问规则,普通变量在工作内存修改之后,回写到主内存,这样其他线程只有在读主内存的时候才能得知。
但是Java内存模型对于volatile赋予不一样的操作,别的线程在使用volatile修饰的变量的时候一定每次都要到主内存读一遍,从这个意义上是立即可知的。但是并不能保证是线程安全的。
比如i++这种操作,A线程对其读入准备修改,B读入准备做++操作。A修改之后,写会主内存,B已经读入了放入栈顶,完全不需要再次从主内存读。这样就会出现线程不安全。究其本质,还是因为++的操作非原子性。
原子性、可见性、有序性
待详细梳理成文
先行发生原则
待详细梳理成文
Java线程模型
Java线程实现、线程调度、状态转换
状态转换
新建、运行、无限期等待、限期等待、阻塞
Java定义的这些线程状态和操作系统层面略有不同,但也正是这些不同,才屏蔽了操作系统的差异,提供了统一个线程模型。
三、高效并发
线程安全实现方法
- 互斥同步(阻塞同步)
悲观锁:使用前先加锁,加锁失败则等待;如果成功,则拿到锁,开始操作。 - 非阻塞同步
全名应该叫基于冲突并发检测的乐观并发策略,这里面的操作和冲突检测其实是硬件层次的支持。
对于这两种其实各自有着适合各自的使用场景。
java实现线程并发的两种方法
synchronize和Lock比较
详情请见:http://my.oschina.net/softwarechina/blog/170859
Java线程中的一些常见问题
- 对synchronized关键字的理解
不管是加在代码上还是加在加在代码块上都是对对象加锁,不存在对代码加锁,这一点非常重要。不过加在代码上是更加灵活,可以对指定对象加锁,加在方法上就只能对该类的this对象加锁。 - Java线程相关方法
比如sleep、与yield区别
wait、notify、notifyAll之间的关系(这三个都是Object的方法)
协调多个线程对共享数据的存取,必须在synchronized语句块内使用
这篇博客对此有详细讲解:http://dylanxu.iteye.com/blog/1322066
其他一些常见细节问题
- Java中怎样停止一个线程
参考:[最佳实践:使用volatile]http://ibruce.info/2013/12/19/how-to-stop-a-java-thread/ - 其他问题
参考:[面试中常见的Java线程问题]http://www.importnew.com/12773.html
参考[Java多线程和并发]:https://segmentfault.com/a/1190000000389806