02- 8锁现象

锁的定义是什么?锁的对象还是Class对象?

示例1:
/**
 * @author 
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(3);//延迟3s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            person.eat();
        },"A").start();

        new Thread(()->{
            person.drink();
        },"B").start();
    }

    static class Person{
        public synchronized void eat(){
            System.out.println("先吃饭");
        }
        public synchronized void drink(){
            System.out.println("先喝水");
        }
    }
}

执行:
在这里插入图片描述
**分析:**sychronized锁的是方法的调用者,两个方法用的是同一个对象,谁先拿到就谁先执行,示例1由于线程A调用eat()的方法前延迟了3s,所以线程B抢到了资源,先行调用了drink().

示例2:
package com.wang.eight;

import java.util.concurrent.TimeUnit;

/**
 * @author wangchangjun
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            person.eat();
        },"A").start();

        new Thread(()->{
            person.drink();
        },"B").start();
    }

    static class Person{
        public synchronized void eat(){
            try {
                TimeUnit.SECONDS.sleep(3);//延迟3s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("先吃饭");
        }
        public synchronized void drink(){
            System.out.println("先喝水");
        }
    }
}

结果:
在这里插入图片描述
**分析:**示例2将延迟加到了eat()中,点击运行后,线程A拿到了资源,进入eat()中,锁住方法,3s后打印信息,eat()执行完毕,线程B执行。

示例3


/**
 * @author
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(2);//延迟2s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            person.eat();
        },"A").start();

        new Thread(()->{
            person.drink();
        },"B").start();
    }

    static class Person{
        public synchronized void eat(){
            try {
                TimeUnit.SECONDS.sleep(2);//延迟2s
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("先吃饭");
        }
        public synchronized void drink(){
            System.out.println("先喝水");
        }
    }
}

结果:
在这里插入图片描述
**分析:**由于线程A延迟原因,线程B抢到资源,调用drink(),2s后,线程A执行走入eat(),再次延迟2s后,打印信息。

示例4:
package com.wang.eight;

import java.util.concurrent.TimeUnit;

/**
 * @author wangchangjun
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            person.eat();
        },"A").start();

        new Thread(()->{
            person.play();
        },"B").start();
    }

    static class Person{
        public synchronized void eat(){
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("先吃饭");
        }
        public synchronized void drink(){
            System.out.println("先喝水");
        }

        public void play(){
            System.out.println("先玩耍");
        }
    }
}

结果:
在这里插入图片描述
分析:由于play()是普通方法,不受锁的影响,所以根据先打印play()。

示例5:增加两个对象,两个线程分别调用

/**
 * @author
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        Person person1=new Person();
        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            person.eat();
        },"A").start();

        new Thread(()->{
            person1.drink();
        },"B").start();
    }

    static class Person{
        public synchronized void eat(){
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("先吃饭");
        }
        public synchronized void drink(){
            System.out.println("先喝水");
        }
    }
}

结果:
在这里插入图片描述
分析:
由于线程A延迟,线程B先执行。2s+2s后打印信息

示例6:增加两个静态方法

/**
 * @author
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            person.eat();
        },"A").start();

        new Thread(()->{
            person.drink();
        },"B").start();
    }

    static class Person{
        public static synchronized void eat(){
            System.out.println("先吃饭");
        }
        public static synchronized void drink(){
            System.out.println("先喝水");
        }

结果:

在这里插入图片描述
分析:
static静态方法类一加载就有了,所以锁的是Class对象,所以按顺序加载的是eat()

示例6

,基于示例5,增加两对象
在这里插入图片描述
结果:
在这里插入图片描述
分析:
两个对象的Class类模板只有一个,static锁的是class模板

示例7

一个静态同步方法,一个普通方法,一个对象调用

package com.wang.eight;

import java.util.concurrent.TimeUnit;

/**
 * @author wangchangjun
 * @Date 2022/7/11
 * @apiNote
 */
public class eightLock {
    public static void main(String[] args) {
        Person person=new Person();
        new Thread(()->{
            person.eat();
        },"A").start();

        new Thread(()->{
            person.drink();
        },"B").start();
    }

    static class Person{
        public static synchronized void eat(){
            try {
               TimeUnit.SECONDS.sleep(2);
          } catch (InterruptedException e) {
               e.printStackTrace();
            }
            System.out.println("先吃饭");
        }
        public  synchronized void drink(){
            System.out.println("先喝水");
        }
    }
}

结果:
在这里插入图片描述
分析:
静态同步锁的是Class模板对象,普通同步方法锁的是调用对象,互不影响,按顺序调用。

示例8

基于示例7,增加两个对象
在这里插入图片描述
结果:
在这里插入图片描述

分析
与例7相同,即使两个对象分别调用,但是锁的对象不同,一个是class对象,一个是调用者对象。

小结
锁的对象无外乎两种,一个是new出来的具体对象,另一个就是唯一的Class模板。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值