一、内容概述
二、简介
1.什么是线程安全?
(1)控制多个线程对某个资源的有序访问或修改
(2)如果一个类在多线程的访问下,其状态是可以
预测的,并且不需要额外的同步,那么这个类
就是线程安全的类
2.
为什么要线程安全?
(1)
线程不安全会造成数据错误,修正数据错误是
费时费力的
(2)
线程不安全会导致程序发生一些异常行为,而
且这种行为很难查找
(3)
线程不安全的现象一般只有在并发量大时才会
出现,因此很难重现
三、 线程不安全产生原因
四、 怎样实现线程安全代码?
线程本地变量,防止内存泄漏
三、 线程不安全产生原因
1.线程工作内存与主存交互
当线程操作某个共享变量时,可能的执行顺序如下:
(1)从主存复制变量到当前工作内存
(2)执行代码,改变共享变量的值
(3)
内存可见性与互斥性
(2)互斥性:在同一时间只能有一个线程对变量的主
存进行操作
将工作内存数据同步回主存
2.
2.
(1)可见性:一个线程的执行结果可以被另一个线程
所看到
四、 怎样实现线程安全代码?
1.不变对象
d.构造后不会更改被引用对象的状态
(1)它的所有字段都是
final
(2)该类声明为
final
(3)不允许
this
引用在构造期间逸出
(4)任何包含对可变对象(如数组、集合或类似
Date
的可变类)引
用的字段:
a.是私有的
b.从来不被返回
b.从来不被返回
c.是对它们所引用对象的唯一引用
2.可变对象
(
1)明确共享资源 :
类变量、实例变量
(
2)利用同步和锁机制 :
解决内存的可见性和互斥性
a)synchronized
3. ThreadLocal类
a)synchronized
保证可见性和互斥性
执行顺序如下:
(
1
)获得同步锁(互斥)
(
2
)清空线程工作内存
(
3
)从主存拷贝变量副本到线程工作内存(对本线程可见)
(
4
)在线程中对变量进行处理
(
5
)将变量从线程工作内存写回到主存(对其他线程可见)
(
6
)释放锁(解除互斥)
b) volatile
(
2
)其他线程也可以看到本线程写入的最新结果
c) wait,notify,notifyAll
用于线程间进行协调,从而使得共享资源不可能达到不一致的状态,因此共享资源是线程安全的
d) j.u.c 包
(4)原子操作
b) volatile
只保证了可见性
直接操作主存
(
1
)本线程可以看到其他线程写入的最新结果
c) wait,notify,notifyAll
用于线程间进行协调,从而使得共享资源不可能达到不一致的状态,因此共享资源是线程安全的
d) j.u.c 包
也包括锁机制(
Lock
)、协调机制(
Condition
)
包结构:
(
1
)线程池
(
2
)同步集合
(
3
)锁
set(T)
T get()
remove()
ThreadLocal
的
OOM:
非单例类,未调用
ThreadLocal.remove
造成的
Memory Leak
五、 常见问题
六、参考资料
五、 常见问题
1.
单例类(不要有实例变量)
(
1
)依靠
Spring
容器依赖注入的类
(
2
)
Servlet
类
2.
常用类(注意其线程安全性描述)
(
1
)
SimpleDateFormat
(
2
)
XPathFactory
六、参考资料
Java Concurrency in Practice
JDK 5.0 Documentation
:
SimpleDateFormat
及
XPathFactory
的
Javadoc
Java
理论与实践
:
变还是不变?
http://www.ibm.com/developerworks/cn/java/j-jtp02183/