JUC-八锁问题学习

demo1

/**
 * 先输出palyGame还是listenMusic?
 * 答案:listenMusic
 * 分析:先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个同步方法,
 * 于是其他与对象有关的同步方法等待,于是him.palyGame()等待。
 * him.listenMusic()执行完毕后,释放锁,也就是释放该该对象,此时him.palyGame()可以获得该对象执行
 */
public class Test1 {
    public static void main(String[] args) throws InterruptedException {
        He him = new He();
        new Thread(() -> {
            him.listenMusic();
        }).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
            him.palyGame();
        }).start();
    }
}

class He {
    public synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public synchronized void listenMusic() {
        System.out.println("listenMusic");
    }
}

demo2

package com.company.lock8;

import java.util.concurrent.TimeUnit;


/**
 * 先输出palyGame还是listenMusic?
 * 答案:listenMusic
 * 分析:先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个同步方法,
 * 于是该方法的实例对象加锁,其他与该实例对象有关的同步方法因拿不到锁而等待。
 * listenMusic()方法内部会睡上5秒,于是5秒后输出listenMusic,执行完毕,释放锁,其他同步方法可以获得该对象,
 * 此时,同步方法palyGame可以被调用执行。
 */
public class Test2 {
    public static void main(String[] args) throws InterruptedException {
        He2 him = new He2();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
            him.palyGame();
        }).start();

    }
}

class He2 {
    public synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo3

 /**
 * 先输出palyGame还是listenMusic?
 * 答案:palyGame
 * 分析:先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个同步方法,
 * 于是其他与对象有关的同步方法等待,但是,此案例中palyGame()是一个普通方法,它不会等待。
 * 所以线程一里面的him.listenMusic()和线程二中的him.palyGame()并行执行,但由于
  * lilistenMusic()方法内部会睡上5秒,于是先输出playgame,5秒后才输出listenMusic.
 */
public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        He3 him = new He3();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
            him.palyGame();
        }).start();

    }
}

class He3 {
    //普通方法
    public  void palyGame() {
        System.out.println("palyGame");
    }

    public synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo4

/**
 * 先输出palyGame还是listenMusic?
 * 答案:palyGame
 * 分析:先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个同步方法,
 * 于是其他与该象有关的同步方法等待,但是,此时两个方法的调用者是两个不同的对象,所以him.palyGame()不会等待。
 * 由于lilistenMusic()方法内部会睡上5秒,于是先输出playgame,后输出listenMusic.
 */
public class Test4 {
    public static void main(String[] args) throws InterruptedException {
        He4 him = new He4();
        He4 him_2 = new He4();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
            him_2.palyGame();
        }).start();

    }
}

class He4 {
    public synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo5

/**
 * 先输出palyGame还是listenMusic?
 * 答案:listenMusic
 * 分析: static synchronized 会锁住类的Class对象,先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个静态同步方法,
 * 于是其他与该类有关的静态同步方法等待.listenMusic()方法内部会睡上5秒,于是5s后输出listenMusic.
 * 当静态同步方法listenMusic()执行完毕后,释放锁。其他与该类有关的静态同步方法可以执行。于是palyGame()被调用执行。
 */
public class Test5 {
    public static void main(String[] args) throws InterruptedException {
        He5 him = new He5();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
          him.palyGame();
        }).start();

    }
}

class He5 {
    public static synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public  static synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo6

/**
 * 先输出palyGame还是listenMusic?
 * 答案:listenMusic
 * 分析: static synchronized 会锁住类的Class对象本身,synchronized锁住的是实例对象。两个不是一个锁。
 * 先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个静态同步方法,
 * 于是其他与该类有关的静态同步方法等待.但palyGame()是一个普通的同步方法,两个不是一个锁,不会等待,同时执行。
 * 由于listenMusic()方法内部会睡上5秒,于先输出输出palyGame,后输出listenMusic.
 */
public class Test6 {
    public static void main(String[] args) throws InterruptedException {
        He6 him = new He6();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
          him.palyGame();
        }).start();

    }
}

class He6 {
    public  synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public  static synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo7

/**
 * 先输出palyGame还是listenMusic?
 * 答案:listenMusic
 * 分析: 还是一样,static synchronized 会锁住类的Class对象本身,两个对象是一个锁。
 * 先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个静态同步方法,
 * 于是其他与该类有关的静态同步方法等待.
 */
public class Test7 {
    public static void main(String[] args) throws InterruptedException {
        He7 him = new He7();
        He7  him_2 = new He7();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
          him_2.palyGame();
        }).start();

    }
}

class He7 {
    public  static synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public  static synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

demo8

/**
 * 先输出palyGame还是listenMusic?
 * 答案:palyGame
 * 分析: 还是一样,static synchronized 会锁住类的Class对象本身,synchronized 所得是实例对象;
 * 一个是类模板,一个是对象,两个就不是一把锁。
 * 先走him.listenMusic()所在线程,调用him.listenMusic(),发现该方法是一个静态同步方法,
 * 于是其他与该类有关的静态同步方法等待,但palyGame()是实例对象调用的,更何况还不是且不是静态同步方法,
 * 所以同步执行。一个睡五秒,一个不睡觉。答案palyGame显而易见.
 */
public class Test8 {
    public static void main(String[] args) throws InterruptedException {
        He8  him = new He8();
        He8  him_2 = new He8();
        new Thread(() -> {
            try {
                him.listenMusic();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        ).start();
        TimeUnit.SECONDS.sleep(1);
        new Thread(() -> {
          him_2.palyGame();
        }).start();

    }
}

class He8 {
    public   synchronized void palyGame() {
        System.out.println("palyGame");
    }

    public  static synchronized void listenMusic() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("listenMusic");
    }
}

总结与注意

  • static synchronized锁的是类对象本身,是模板。而synchronizeds锁的是实例对象。
  • 当一个线程的同步方法或同步代码块(不管是静态同步方法还是普通同步方法)执行时,它总先要获得锁,才能执行,如果公共资源,也就是这个锁还被其他同步方法或同步代码块霸占着,没有释放,那么这个同步方法必须等待这个锁被释放才能执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值