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

Posted luoyu113

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区分同步代码块静态同步方法非静态同步方法的锁相关的知识,希望对你有一定的参考价值。

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

  • 同步代码块可以使用自定义的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;
        }
    }

以上是关于区分同步代码块静态同步方法非静态同步方法的锁的主要内容,如果未能解决你的问题,请参考以下文章

Java面试

Java线程:线程的同步与锁

多线程基础

聊聊synchronized的锁问题

Thread-线程的同步

Java高并发之同步异步