synchronized到底锁的是什么??

先说结论,锁无非是锁两种:

  1. 非静态方法锁的当前实例对象this
  2. 静态方法锁的是当前类的class对象
  3. 代码块锁的是指定的对象

1、synchronzed修饰普通方法

package juctest;

import java.util.concurrent.TimeUnit;

public class LockTest1 {

    /**
     * 两个线程访问同一个synchronzied修饰的方法,资源类
     * 其中谁先抢占着锁谁先执行。
     * synchronzied锁的是调用对象,因为对象都是phone,所以是先执行发短信,再执行打电话
     * 不用synchronized修饰的方法不参与锁的抢占
     * 所以执行顺序应该是    你好====>发短信=====》打电话
     * */

    public static void main(String[] args) {
        //定义共享资源类
        Phone phone = new Phone();
        new Thread(()->{
            phone.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();

        new Thread(()->{
            phone.hello();
        },"c").start();

    }


}


class Phone{//资源类

    synchronized  void  sms(){//发短信
        try {
            //进来线程先睡五秒钟,这不会释放锁
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"=>发短信");
    }


    synchronized void call(){//打电话
        System.out.println(Thread.currentThread().getName()+"=>打电话");
    }

    void hello(){
        System.out.println(Thread.currentThread().getName()+"=>你好");
    }

}

2、synchronized修饰静态方法

package juctest;

import java.util.concurrent.TimeUnit;

public class LockTest2 {

    /**
     * synchronzied修饰静态方法锁的是类的class模板,同一个类只有一个class模板
     * 所以线程A先抢占到锁,所以它先执行,sleep方法不会释放锁,wait方法会释放锁
     * 所以执行顺序是发短信=====》打电话
     *
     * 如果是不同的类,就是其实没有并发问题了,访问的不是同一个资源类,
     * 再一个说,两个线程访问不同的类中的static方法,是没有先后的,锁不住的
     *
     *
     * */

    public static void main(String[] args) {
        //定义共享资源类
        Phone2 phone2 = new Phone2();
        new Thread(()->{
            phone2.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone2.call();
        },"B").start();

    }



}


class Phone2{//资源类

    synchronized static void  sms(){//发短信
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"=>发短信");
    }


    synchronized  static void call(){//打电话
        System.out.println(Thread.currentThread().getName()+"=>打电话");
    }

}
package juctest;

import java.util.concurrent.TimeUnit;

public class LockTest3 {

    /**
     * synchronzied修饰静态方法锁的是类的class模板,同一个类只有一个class模板
     *  一个资源类中的两个方法:
     *  1、一个静态方法,一个普通方法,一个锁的是class,一个锁的是调用对象,所以两个没有具体的先后顺序(如果同时执行的话)
     *      我们这里有sleep(),所以输出   打电话===》发短信
     *  2、两个对象同理。
     *
     * */

    public static void main(String[] args) {
        //定义共享资源类
        Phone3 phone3 = new Phone3();
        new Thread(()->{
            phone3.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone3.call();
        },"B").start();

    }

}

class Phone3{//资源类
    synchronized static void  sms(){//发短信
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"=>发短信");
    }

    synchronized  void call(){//打电话
        System.out.println(Thread.currentThread().getName()+"=>打电话");
    }
}

3、synchronized修饰代码块

package juctest;

import java.util.concurrent.TimeUnit;

public class LockTest4 {

    /**
     * synchronzied修饰同步代码块锁的是指定的对象
     * 这里我们用的是调用方对象的class文件,Phone4唯一的,
     * 所以当线程A拿到锁sleep的过程中,那么线程B执行到同步代码块的时候只能等待线程A释放锁
     * 所以执行顺序为 发短信=====》打电话
     *
     *
     * 如果我们同步代码块传的对象为new Object(),那么每个线程进来的时候都会锁一个新的对象,
     * 所以这种写法是什么都锁不住的,执行结果为  打电话===》发短信
     *
     * */

    public static void main(String[] args) {
        //定义共享资源类
        Phone4 phone4 = new Phone4();
        new Thread(()->{
            phone4.sms();
        },"A").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone4.call();
        },"B").start();

    }

}

class Phone4{//资源类
    void  sms(){//发短信
         synchronized (this.getClass()){//new Object()
             try {
                 TimeUnit.SECONDS.sleep(5);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             System.out.println(Thread.currentThread().getName()+"=>发短信");
         }

    }

      void call(){//打电话
        synchronized (this.getClass()){//new Object()
            System.out.println(Thread.currentThread().getName()+"=>打电话");
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值