线程的安全问题
同步机制解决线程安全问题
方式一:同步代码块
synchronized(obj){
// 需要被同步的代码
}
synchronized(this){
}
synchronized(Windows.class){
}
注:
- 操作共享数据的代码,即为需要被同步的代码
- 同步监视器,俗称:锁。
- 任何一个类的对象,都可以充当锁,要求多个线程必须要共用同一把锁
- 补充:在实现Runnable接口创建多线程方式中,我们可以考虑使用this充当同步监视器
方式二:同步方法
如果操作的共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明同步的
public synchronized void 方法名(){}
// 使用同步方法解决继承Thread类的线程问题
public static synchronized void 方法名(){}
注:
- 同步方法仍然设计了同步监视器,只是不用显式的声明
- 非静态的同步方法,同步监视器:this
- 静态的同步方法,同步监视器:类名.class
方式三:JDK5.0新增 --------> Lock锁
private ReentrantLock lock = new ReentrantLock();
try{
// 调用lock()
lock.lock();
...
}finally{
//调用解锁方法unlock()
lock.unlock();
}
同步的方式,解决了线程的安全问题,但解决同步代码时,只能有一个线程参与,其他线程等待,相当于是一个单线程的过程,效率低。
线程的死锁问题
解决方法:
- 专门的算法、原则
- 尽量减少同步资源的定义
- 尽量避免嵌套同步
面试题:synchronized 与 Lock 的异同?
同:二者都能解决线程安全问题
异:
- synchronized机制在执行完相应的同步代码以后,会自动的释放同步监视器
- Lock 需要手动的启动同步(Lock()),同时结束同步需要手动的实现(unlock(())