Java------synchronized理解

synchronized理解

synchronized是一个排它锁,既能够锁方法,又能够锁代码块。
用于实现线程同步,多个线程依次获取资源。

synchronized 在方法上,且非静态方法

此时锁的是方法调用者。
示例:两个线程
结果:先输入B,在输出A

public class Test {

    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            try {
                data.fun01();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                data.fun02();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }


}

class Data{

    public void fun01() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("A----1");
    }
    public void fun02() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        System.out.println("B----2");
    }
}

在方法上加上synchronized ,就会出现:
3秒后输出A
再过1秒,输出B的情况。

package com.springdemo.demo;

import java.util.concurrent.TimeUnit;

public class Test {

    public static void main(String[] args) {
        Data data = new Data();
        new Thread(()->{
            try {
                data.fun01();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(()->{
            try {
                data.fun02();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }


}

class Data{

    public synchronized  void fun01() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("A----1");
    }
    public synchronized void fun02() throws InterruptedException {
        TimeUnit.SECONDS.sleep(1);
        System.out.println("B----2");
    }
}

如果将fun02()上的synchronized 去掉就会出现,先输出B再输出A的情况。
同样的如果是两个对象,

Data data = new Data();
Data data2 = new Data();

这两个对象分别调用fun01,和fun02,也不会出现资源争夺的情况,
结果就是先输出B,再输出A。

synchronized关键字在静态方法上

class Data{

    public synchronized static void fun01() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("A----1");
    }
    public synchronized static void fun02() throws InterruptedException {
        System.out.println("B----2");
    }
}

结果表现:则是3秒后,先输出A,再输出B。依然对资源进行线程的排队获取的处理。

synchronized关键字修饰代码块

public static void main(String[] args) {
        Data2 data2 = new Data2();
        for (int i = 0;i<5;i++){
            new Thread(()->{
                try {
                    data2.fun3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
    
class Data2{

    public   void fun3() throws InterruptedException {
        System.out.println("3----start");
        TimeUnit.SECONDS.sleep(3);
        System.out.println("3----end");
    }

}

此时结果是:输出5个start,过3秒后,再输出5个end。
加上synchronized 锁代码块,this锁的对象

    public   void fun3() throws InterruptedException {
        synchronized (this){
            System.out.println("3----start");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("3----end");
        }

    }

结果:此时会排队,一个start,一个end,循环5次。
此时的this,代表当前的实例化对象。此时5个线程,公用一个data2 对象。
将data2放到循环中

public static void main(String[] args) {
        for (int i = 0;i<5;i++){
            new Thread(()->{
                try {
                    Data2 data2 = new Data2();
                    data2.fun3();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

此时,又是同时开始,同时结束,输出5次start,再输出5次end。
如果synchronized (Data2.class),此时锁的是Data2这个类。

public   void fun3() throws InterruptedException {
        synchronized (Data2.class){
            System.out.println("3----start");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("3----end");
        }

    }

此时尽管循环创建新的data2对象,也依然会排队。start、end依次循环输出。
如果synchronized (一个变量)

public   void fun3() throws InterruptedException {
        String num = "1";
        synchronized (num){
            System.out.println("3----start");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("3----end");
        }

    }

结果:此时需要排队…
但是,如果这个num是参数传进来的呢?是否排队输出?

  public static void main(String[] args) {
        for (int i = 0;i<5;i++){
            new Thread(()->{
                try {
                    Data2 data2 = new Data2();
                    String s="A";
                    data2.fun3(s);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
 class Data2{

    public   void fun3(String num) throws InterruptedException {
        synchronized (num){
            System.out.println("3----start");
            TimeUnit.SECONDS.sleep(3);
            System.out.println("3----end");
        }

    }

}

此时是需要排队输出,因为此时的String s=“A”;是常量池中拿出,只有一个。
如果传入的变量不是同一个呢?输出结果是什么样?

public static void main(String[] args) {
        for (int i = 0;i<5;i++){
            new Thread(()->{
                try {
                    UUID uuid = UUID.randomUUID();
                    Data2 data2 = new Data2();
                    String s="asdasdasdasdasd"+uuid;
                    data2.fun3(s);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

答案:此时不需要排队,会先输出5个start,再输出5个end。因为此时每个a都是单独的对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值