多线程的安全问题
一. 同步机制
线程具有随机性,当多个线程同时在操作同一个共享资源时,一个语句对多条语句只执行了一部分还没有执行完,另一个线程便参与进来执行,导致共享数据的错误。
为了处理这种共享资源竞争,可以使用java提供的同步机制。
所谓同步机制指的是多个线程操作一个对象时,应该保持对象数据的统一性和完整性。即多个线程之间要排队,一个一个对共享资源进行操作。在一个线程执行过程中,其他线程不能参与执行,只能让一个线程都执行完。
java语言通过synchronized关键字来控制多线程间的同步。
java语言中有两种同步形式:同步方法和同步代码块。
1.同步方法
1.1.同步非静态方法
public synchronized void method();
同步非静态方法,默认同步锁是this
1.2.同步静态方法
public static synchronized void method();
同步静态方法,默认同步锁是当前方法所在类的.class对象,不能和this连用。
synchronized关键字要注意:
a.synchronized关键字不能被继承
b.在定义接口方法时不能使用synchronized关键字
c.构造方法不能使用synchronized关键字,但可以使用synchronized代码块
d.synchronized关键字可以自由放置。synchronized关键字通常放在方法的返回类型前面。在非静态方法中,synchronized关键字还可以放置在方法定义的最前面。在静态方法中,synchronized 关键字可以放在static的前面。
2.同步代码块
synchronized(Object obj){
......需要同步的代码块
}
同步代码块,默认的同步锁是obj
二.死锁
1.死锁的产生
死锁是由于两个或多个线程都无法得到相应的监视器而造成相互等待的现象。导致死锁的根源在于不适当的运用synchronized关键字来管理线程对特定对象的访问,其产生的充要条件如下:
a.互斥:即多个线程不能同时使用同一资源,若线程A使用该资源时,线程B只能等待A释放后才能使用。
b.占有等待:即某线程必须同时拥有N个资源才能完成任务,否则它将占用已经拥有的资源,直到拥有它所需的所有资源为止。
c.非剥夺:即所有线程的优先级都相同,不能在别的线程没有释放资源的情况下,夺走其已占有的资源。
d.循环等待:第一个线程等待其他线程,而后者又在等待第一个线程。
因为要发生死锁,这四个条件必须同时满足,所以要防止死锁的话,只需要破坏其中一个条件即可。
2.避免死锁。
因为要发生死锁,这四个条件必须同时满足,所以要防止死锁的话,只需要破坏其中一个条件即可。
避免死锁的有效原则:
a.当线程因某个条件为满足而受阻时,不能让其继续占用资源。
b.如果有多个对象需要互斥访问时,应确定线程获得锁的顺序,并保证整个程序以相反的顺序释放锁。