您的位置:首页 > 编程语言

编写线程安全的代码

2016-04-08 14:38 274 查看
来自http://blog.csdn.net/gtuu0123/article/details/6358578



一、内容概述





二、简介

1.什么是线程安全?

(1)控制多个线程对某个资源的有序访问或修改
(2)如果一个类在多线程的访问下,其状态是可以预测的,并且不需要额外的同步,那么这个类就是线程安全的类
2.为什么要线程安全?

(1)线程不安全会造成数据错误,修正数据错误是费时费力的
(2)线程不安全会导致程序发生一些异常行为,而且这种行为很难查找
(3)线程不安全的现象一般只有在并发量大时才会出现,因此很难重现

三、线程不安全产生原因

1.线程工作内存与主存交互

当线程操作某个共享变量时,可能的执行顺序如下:

(1)从主存复制变量到当前工作内存
(2)执行代码,改变共享变量的值
(3)

将工作内存数据同步回主存

2.

内存可见性与互斥性

(1)可见性:一个线程的执行结果可以被另一个线程所看到

(2)互斥性:在同一时间只能有一个线程对变量的主存进行操作



四、
怎样实现线程安全代码?

1.不变对象

(1)它的所有字段都是 final
(2)该类声明为 final
(3)不允许 this 引用在构造期间逸出
(4)任何包含对可变对象(如数组、集合或类似 Date 的可变类)引用的字段:
a.是私有的

b.从来不被返回
c.是对它们所引用对象的唯一引用

d.构造后不会更改被引用对象的状态
2.可变对象
(1)明确共享资源:类变量、实例变量
(2)利用同步和锁机制:解决内存的可见性和互斥性

a)synchronized

保证可见性和互斥性
执行顺序如下:
(1)获得同步锁(互斥)
(2)清空线程工作内存
(3)从主存拷贝变量副本到线程工作内存(对本线程可见)
(4)在线程中对变量进行处理
(5)将变量从线程工作内存写回到主存(对其他线程可见)
(6)释放锁(解除互斥)

b)volatile

只保证了可见性
直接操作主存
(1)本线程可以看到其他线程写入的最新结果

(2)其他线程也可以看到本线程写入的最新结果

c)wait,notify,notifyAll

用于线程间进行协调,从而使得共享资源不可能达到不一致的状态,因此共享资源是线程安全的

d) j.u.c包

也包括锁机制(Lock)、协调机制(Condition)
包结构:
(1)线程池
(2)同步集合
(3)锁

(4)原子操作

3. ThreadLocal类

线程本地变量,防止内存泄漏

set(T)
T get()
remove()



ThreadLocal的OOM:非单例类,未调用ThreadLocal.remove造成的Memory Leak

[java]
view plain
copy

public class A {
private final ThreadLocal t = new ThreadLocal();
public void a() {
t.set(someObject);
}
public static void main(String[] args) {
while(true) {
new A().a();
}
}
}



五、
常见问题

1. 单例类(不要有实例变量)
(1)依靠Spring容器依赖注入的类
(2)Servlet类
2. 常用类(注意其线程安全性描述)
(1)SimpleDateFormat
(2)XPathFactory

[java]
view plain
copy

private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(“yyyy-MM-dd”);
public String formatDate(Date d) {
return DATE_FORMATTER.format(d);
}

六、参考资料

Java Concurrency in Practice
JDK 5.0 Documentation:SimpleDateFormat及XPathFactory的Javadoc



Java 理论与实践:
变还是不变?http://www.ibm.com/developerworks/cn/java/j-jtp02183/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: