区分同步代码块、静态同步方法、非静态同步方法的锁

同步代码块、静态同步方法、非静态同步方法的锁分别是:

  • 同步代码块可以使用自定义的Object对象,也可以使用this或者当前类的字节码文件(类名.class);
  • 静态同步方法的锁是当前类的字节码文件(类名.class);
  • 非静态同步方法的锁是this;

证明方法:

  • 两个线程之间实现同步,一个线程使用同步代码块,一个线程使用同步方法。
  • 如果这两个线程同步了,说明了使用的是同一个锁;
创建线程类(以售票为例)
/**
 * @methodDesc 售票线程类
 */
public class ThreadTrain extends Thread {
    // 总共又100张
    private static int trainCount = 100;    
    protected static boolean flag = true;

    @Override
    public void run() {     
        while (trainCount > 0) {
            if (flag) { // 执行同步代码块,this锁
                System.out.println("flag==="+flag);
                // 出售火车票
                sale1();        
            }else {
                System.out.println("flag==="+flag);
                // 出售火车票
                sale11();
            }
            flag = !flag;
        }
    }
    
    // 同步代码块
    public void sale1() {
        // 同步代码块,包裹需要解决线程安全问题的代码块,两个线程同时访问
        synchronized (this) { // 只能有一个线程进行访问,必须拿到锁的时候才能访问
            if (trainCount > 0) { // 不加判断,会出现出售第101张票的情况
                System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "张票");
                trainCount--;
            }
        }
    }
    
    // 静态同步代码块
    public void sale2() {
        // 同步代码块,包裹需要解决线程安全问题的代码块,两个线程同时访问
        synchronized (ThreadTrain.class) { // 只能有一个线程进行访问,必须拿到锁的时候才能访问
            if (trainCount > 0) { // 不加判断,会出现出售第101张票的情况
                System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "张票");
                trainCount--;
            }
        }
    }

    // 同步方法
    public synchronized void sale11() {     
        if (trainCount > 0) { // 不加判断,会出现出售第101张票的情况
            System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "张票");
            trainCount--;
        }
    }
    
    // 静态同步方法
    public static synchronized void sale22() {      
        if (trainCount > 0) { // 不加判断,会出现出售第101张票的情况
            System.out.println(Thread.currentThread().getName() + ", 出售第" + (100 - trainCount + 1) + "张票");
            trainCount--;
        }
    }
}
创建测试类
/**
 * @methodDesc 多线程模拟售票问题
 */
public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        // 创建售票线程对象
        ThreadTrain train1 = new ThreadTrain();
        // 创建多个售票窗口,并给其取别名
        Thread t1 = new Thread(train1, "窗口1");
        Thread t2 = new Thread(train1, "窗口2");
        t1.start(); 
        t2.start();
    }
}
验证方法
  • 验证非静态同步方法,修改run方法为
        public void run() {     
        while (trainCount > 0) {
            if (flag) { // 执行同步代码块,this锁
                System.out.println("flag==="+flag);
                // 出售火车票
                sale1();        
            }else {
                System.out.println("flag==="+flag);
                // 出售火车票
                sale11();
            }
            flag = !flag;
        }
    }
  • 验证静态同步方法,修改run方法为
        public void run() {     
        while (trainCount > 0) {
            if (flag) { // 执行同步代码块,this锁
                System.out.println("flag==="+flag);
                // 出售火车票
                sale2();        
            }else {
                System.out.println("flag==="+flag);
                // 出售火车票
                sale22();
            }
            flag = !flag;
        }
    }

猜你喜欢

转载自www.cnblogs.com/luoyu113/p/10548317.html