synchronized锁住的到底是什么

本文详细探讨了Java中线程同步的不同方式,包括静态方法锁类、非静态方法锁实例、代码块锁对象与作用域。通过实例展示了synchronized在类、对象和代码块上的应用,以及它们如何影响线程间的交互和执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

论证

  • 修饰方法
    静态方法 锁定的是类
    非静态方法 锁定的是实例对象本身

  • 修饰代码块 锁定的是传入的对象

  • 作用域为全局

1.首先创建线程调用类

修饰方法时

public class TestPrint {
    public static void main(String[] args) {
        Print print= new Print();
        new Thread(()->{
            print.fun1();
        },"A").start();
        new Thread(()->{
            print.fun2();
        },"A").start();
    }
}
class Print{
    public void fun1(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public void fun2(){
        System.out.println("2....");
    }
}

控制台为
在这里插入图片描述

2.修饰非静态方法 锁住的是实例对象本身

一个对象(资源类实例化)里面如果有多个synchronized方法,某一时刻只要有一个线程去访问其中一个synchronized方法,其他线程都只能在外等待。换句话说,同一时刻,只能有唯一的线程去访问这些synchronized方法,锁的是当前对象的this,被锁定后,其他的线程都不能进入到当前对象的其他synchronized方法。

把两个方法(非静态)加上synchronized修饰 A线程获取到print对象后 B线程只能在外等待

public class TestPrint {
    public static void main(String[] args) {
        Print print= new Print();
        new Thread(()->{
            print.fun1();
        },"A").start();
        new Thread(()->{
            print.fun2();
        },"B").start();
    }
}
class Print{
    public synchronized void fun1(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public synchronized void fun2(){
        System.out.println("2....");
    }
}

在这里插入图片描述
把两个方法(非静态)加上synchronized修饰 print对象执行A线程 print1对象执行B线程 无需等待

public class TestPrint {
    public static void main(String[] args) {
        Print print = new Print();
        Print print1 = new Print();
        new Thread(()->{
            print.fun1();
        },"A").start();
        new Thread(()->{
            print1.fun2();
        },"B").start();
    }
}
class Print{
    public synchronized void fun1(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public synchronized void fun2(){
        System.out.println("2....");
    }
}

在这里插入图片描述

只对fun1(非静态)加上synchronized修饰 A线程获取到print对象后 B也可以执行fun2 无需等待

public class TestPrint {
    public static void main(String[] args) {
        Print print = new Print();
        new Thread(()->{
            print.fun1();
        },"A").start();
        new Thread(()->{
            print.fun2();
        },"B").start();
    }
}
class Print{
    public synchronized void fun1(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public  void fun2(){
        System.out.println("2....");
    }
}

在这里插入图片描述

3.修饰静态方法 锁定的是类(可以说 类是Class的对象)

  对两个方法都修饰 synchronized static   看出print1对象需要等待print对象执行完才能执行
public class TestPrint {
    public static void main(String[] args) {
        Print print = new Print();
        Print print1 = new Print();
        new Thread(()->{
            print.fun1();
        },"A").start();
        new Thread(()->{
            print1.fun2();
        },"A").start();
    }
}
class Print{
    public static synchronized void fun1(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("1....");
    }
    public static synchronized void fun2(){
        System.out.println("2....");
    }
}

在这里插入图片描述

4. 修饰代码块时

创建for循环线程调用 可看出是并行的


public class TestPrint {
    public static void main(String[] args) {
      Print print = new Print();
      for (int i =0;i< 5;i++){
          new Thread(()->{
              print.fun();
          },"A").start();
      }
    }
}
class Print{
    public  void fun(){
        System.out.println("开始....");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("结束....");
    }
}

在这里插入图片描述
当我加入this 开始等待了 五个线程只有一个资源(对象) this锁住的调用的对象

public class TestPrint {
    public static void main(String[] args) {
      Print print = new Print();
      for (int i =0;i< 5;i++){
          new Thread(()->{
              print.fun();
          },"A").start();
      }
    }
}
class Print{
    public  void fun(){
        synchronized (this){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述
当我把new Print()放到循环里面 就变成了每个线程各有一个资源(对象) 结果就是并行

public class TestPrint {
    public static void main(String[] args) {
      for (int i =0;i< 5;i++){
          Print print = new Print();
          new Thread(()->{
              print.fun();
          },"A").start();
      }
    }
}
class Print{
    public  void fun(){
        synchronized (this){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述
当我synchronized(类.Class)之后 锁着的是当前类 无论多少个对象来访问都需等待

public class TestPrint {
    public static void main(String[] args) {
      for (int i =0;i< 5;i++){
          Print print = new Print();
          new Thread(()->{
              print.fun();
          },"A").start();
      }
    }
}
class Print{
    public  void fun(){
        synchronized (Print.class){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述
当我用“1”放入()中 代码也会等待 “1”只有一份

public class TestPrint {
    public static void main(String[] args) {
      Print print = new Print();
      for (int i =0;i< 5;i++){
          new Thread(()->{
              print.fun();
          },"A").start();
      }
    }
}
class Print{
    public  void fun(){
        synchronized ("1"){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述
当我用num参数放入()中 让调用者传入num 如果num是同一个地址 线程也会等待

public class TestPrint {
    public static void main(String[] args) {
      Print print = new Print();
      for (int i =0;i< 5;i++){
          Integer num = 1;
          new Thread(()->{
              print.fun(num);
          },"A").start();
      }
    }
}
class Print{
    public void fun(Integer num){
        synchronized (num){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述
当我用num参数放入()中 让调用者每次传入new num num地址不同 线程不会等待

public class TestPrint {
    public static void main(String[] args) {
      Print print = new Print();
      for (int i =0;i< 5;i++){
          Integer num = new Integer(1);
          new Thread(()->{
              print.fun(num);
          },"A").start();
      }
    }
}
class Print{
    public void fun(Integer num){
        synchronized (num){
            System.out.println("开始....");
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("结束....");
            }
    }
}

在这里插入图片描述

5. synchronized()修饰代码块时 锁住的作用域

建立person类

在这里插入代码片
@Service
public class Person {
    public void fun1(){
        synchronized ("111"){
            System.out.println("存钱开始");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("存钱结束");
        }
    }
}

建立student类

@Service
public class Student {
    public void fun2(){
    synchronized("111"){
            System.out.println("花钱开始");
            System.out.println("花钱结束");
        }
    }
}

建立测试controller

@RestController
public class ceshi {
    @Autowired
    Person person;
    @Autowired
    Student student;
    @RequestMapping("/xian")
    public void ceeshi(){
        new Thread(()->{
            person.fun1();
        },"A").start();
        new Thread(()->{
            student.fun2();
        },"B").start();
    }
}

当我用postman访问接口 student对象会等待person对象执行完 才执行 由此可得synchronized修饰代码块()传入参数地址一样 作用域为全局

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值