C、每个线程调用对象的任意方法后,该对象状态保持合理状态
不可变类总是线程安全的,因为它的对象状态是不可改变的,但可变类对象需要额外的方法来保证线程安全。
例如Account就是一个可变类,它的money就是可变的,当2个线程同时修改money时,程序就会出现异常或错误。
所以要对Account设置为线程安全的,那么就需要用到同步synchronized关键字。
下面的方法用synchronized同步关键字修饰,那么这个方法就是一个同步的方法。这样就只能有一个线程可以访问这个方法,
在当前线程调用这个方法时,此方法是被锁状态,同步监视器是this。只有当此方法修改完毕后其他线程才能调用此方法。
这样就可以保证线程的安全,处理多线程并发取钱的的安全问题。
public synchronized void drawMoney(double money) {
//取钱操作
}
注意:synchronized可以修饰方法、代码块,但不能修饰属性、构造方法
可变类的线程安全是以降低程序的运行效率为代价,为了减少线程安全所带来的负面影响,可以采用以下策略:
A、不要对线程安全类的所有方法都采用同步模式,只对那些会改变竞争资源(共享资源)的方法进行同步。
B、如果可变类有2中运行环境:单线程环境和多线程环境,则应该为该可变提供2种版本;线程安全的和非线程安全的版本。
在单线程下采用非线程安全的提高运行效率保证性能,在多线程环境下采用线程安全的控制安全性问题。
任何线程进入同步代码块、同步方法之前,必须先获得对同步监视器的锁定,那么何时会释放对同步监视器锁定?
程序无法显示的释放对同步监视器的锁定,线程可以通过以下方式释放锁定:
A、当线程的同步方法、同步代码库执行结束,就可以释放同步监视器
B、当线程在同步代码库、方法中遇到break、return终止代码的运行,也可释放
C、当线程在同步代码库、同步方法中遇到未处理的Error、Exception,导致该代码结束也可释放同步监视器
D、当线程在同步代码库、同步方法中,程序执行了同步监视器对象的wait方法,导致方法暂停,释放同步监视器
下面情况不会释放同步监视器:
A、当线程在执行同步代码库、同步方法时,程序调用了Thread.sleep()/Thread.yield()方法来暂停当前程序,当前程序不会释放同步监视器
B、当线程在执行同步代码库、同步方法时,其他线程调用了该线程的suspend方法将该线程挂起,该线程不会释放同步监视器。注意尽量避免使用suspend、resume
[java]
作者 itm_hadf