2.共享资源的代码区,被称为临界区
同步方法 1.Java的多线程安全支持还提供了同步方法,使用synchronized关键字来修饰某个方法,该方法被称为同步方法,同步方法的同步监视器是this,也就是调用该方法的对象 2.上面取钱的例子中,可以考虑把Account类中的setBalance方法去掉,增加一个同步方法,如下 // 注意synchronized修饰 public synchronized void draw(double drawAmount){ if(account.getBalance()>=drawAmount){ // ... }else{ // ... } 释放同步监视器的锁定 任何线程进入同步方法、同步代码块之前,必须先获得对同步监视器的锁定,那么何时会释放同步监视器的锁定呢? 线程执行同步代码块或同步方法时,执行结束…,遇到return break…,遇到未处理的Error Exception…,程序执行了同步监视器对象的wait()方法,则当前线程暂停,并释放同步监视器如下情况下,线程不会释放同步监视器: 1. …,程序调用Thread.sleep(),Thread.yield()方法来暂停当前线程的执行,当前线程不会释放同步监视器。 2. …,其他线程调用了该线程的suspend()方法将该线程挂起。当然,应尽量避免使用suspend()和resume()方法来控制线程。 * 同步锁(Lock) 1. Lock接口,实现类是ReentrantLock(可重入锁) 2. ReadWriteLock(读写锁)接口,实现类是ReentrantReadWriteLock,该实现类在java8中大多数场景下可被StampedLock替代。 3. 实现线程安全的控制中,比较常用的是ReentrantLock,代码格式如下: 4.同步锁和同步方法、同步代码块的比较:虽然同步方法和同步代码块的范围机制使得多线程安全变成非常方便,而且还可以避免很多设计锁的常见变成错误,但有时也需要以更灵活的方式使用锁。Lock提供了同步方法和同步代码块所没有的其他功能。
class x{ // 定义锁对象 private final ReentrantLock lock = new ReentrantLock(); // 定义需要保证线程安全的方法 public void m(){ lock.lock(); try{ // 需要保证线程安全的代码 // ...method body }finally { lock.unlock(); } } } 死锁 1.当两个线程互相等待对方释放同步监视器时就会发生死锁,Java虚拟机没有检测,也没有采取措施来处理死锁情况。一旦出现,整个程序不会发出任何异常,也不会给提示,只是所有的线程处于阻塞状态,无法继续。 由于Thread类的suspend方法很容易导致死锁,所以Java不推荐使用该方法来暂停线程的执行