【Java并发】线程安全

什么是线程安全?

当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不必作其他的协调,这个类的行为仍然是正确的,则称这个类是线程安全的类。

 

无状态的类是线程安全的

如果一个类是无状态的:不包含域也没有引用其他类的域。一次特定计算的瞬时状态会唯一地存在本地变量中,这些本地变量存储在线程的栈中,只有执行线程才能访问。

 

编写线程安全的代码,本质上就是管理对状态 的访问,而且是共享的 /可变的 状态。

关于状态:一个对象的状态就是该对象的数据,存储在状态变量中,如实例域或静态域,还包括附属对象的域。如HashMap的状态一部分存储在对象本身中,同时也存储到很多Map.Entry对象中。

关于共享:一个变量可以被多个线程同时访问。

关于可变:变量的值在其生命周期内可以改变。


只要有多于一个的线程访问给定的状态变量,而且其中某个线程会写入该变量,此时必须使用同步来协调线程对该变量的访问。

Java中首要的同步机制是synchronized关键字,它提供了独占锁。另外,“同步”还包括volatile变量,显示锁和原子变量的使用。


面对一个有多线程访问隐患的程序,可以从以下三个方法来修复:

1.不要使用跨线程的共享变量;

2.使状态变量变为不可变的;

3.在任何访问状态变量的时候使用同步


注意一开始就将一个类设计成是线程安全的,比在后期重新修复更容易,并且并发访问共享状态变量带来的问题往往不好重现。 另外,设计线程安全的类时,要充分利用优秀的面向对象技术——如封装。

 


处理并发程序常见的问题:

1.竞争条件 Race Condition

    a.原子操作问题

自增,自减操作不是原子操作,是读-改-写复合操作,可以用线程安全的原子变量(在java.util.concurrent.atomic包中)来作为计数器。

    b.检查再运行

例如:你观察到一些事情为真(文件x不存在),然后(then)基于你的观察去执行一些动作(创建文件x);事实上,从观察到执行操作的这段时间里,观察结果可能已经失效了(有人在此期间创建了文件x),从而引发错误(非预期的异常,重写数据或者破坏文件)。

再例如惰性初始化。

 

操作共享状态的复合操作必须是原子的,以避免上面的竞争条件,通过对该复合操作加锁 可以确保其行为是原子的。

 

问题:只有在写入共享变量时才需要同步么?

3.1节

 

在java中有哪些保证线程安全的机制或者措施?

锁机制(implicit lockexplicit lock )参见 http://nemogu.iteye.com/blog/1409879




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值