1.由于系统的线程调度具有一定的随机性,当使用多个线程访问同一个数据时,很容易“偶然”出现线程安全问题,解决这种问题的主要方法是使用同步代码块、同步方法、同步锁等。
1.1 同步代码块
语法如下:synchronized(obj){//同步代码块},其中obj是同步监视器(临界资源/共享变量),任何一个时刻只有一个线程可以获得同步监视器的锁定。
1.2 同步方法
在访问同步监视器的方法的定义中使用synchronized修饰,如:public synchronized void fun(){};
1.3 同步锁
Lock可以控制多个线程对共享资源进行访问,分为ReadWriteLock(读写锁),ReentrantLock(可重入锁,较常用)。使用格式如下:
class X
{
private final ReentrantLock lock=new ReentrantLock();
public void m()
{
lock.lock();
try
{
//访问临界资源
}
finally
{
lock.unlock();//建议在finally中释放锁
}
}
}
但上面的同步方式可能会出现死锁的现象。
比如a对象中的方法a1调用b对象的同步synchronized方法b2,需对a加锁,同时b对象的另一方法b1又调用a对象的a2,需对b加锁,但此时已对a,b对象加锁,二者均不能执行下去。