同一个类中多个持有不同锁的同步代码块会不会阻塞--关于同步代码块的一个疑问验证--

结论是:

在同一个类中,多个线程同时访问同一对象的持有不同锁的同步代码块不会发生阻塞。

一、直接测试。供测试的共享对象的类:(方法changeA,changB持不同锁)

public class Demo {
    //新建两个对象供同步代码块加锁
    Student a = new Student(1, "A");
    Student b = new Student(2, "B");
    public void changeA() {
        //加锁a
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "进入同步代码块的时间:" + System.currentTimeMillis());
            a.setId(3);
            //为了观察明显,线程持锁跑3s
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
            }
            System.out.println(Thread.currentThread().getName() + "退出代码块的时间:" + System.currentTimeMillis());
        }
    }
    public void changeB() {
        //加锁b
        synchronized (b) {
            System.out.println(Thread.currentThread().getName() + "进入同步代码块的时间:" + System.currentTimeMillis());
            b.setId(4);
            //为了观察明显,线程持锁跑3s
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
            }
            System.out.println(Thread.currentThread().getName() + "退出代码块的时间:" + System.currentTimeMillis());
        }
    }
    public Student getA() {
        return a;
    }
    public Student getB() {
        return b;
    }
}

Student类包含id和name属性;

测试方法:

public class Main {
    public static void main(String[] args) {
        Demo demo = new Demo();
        //新建两个线程分别进入changeA,changeB方法,验证是否会阻塞
        Thread threada = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("--a的初始值"+demo.getA());
                demo.changeA();
                System.out.println("--a更新后值"+demo.getA());
            }
        });
        Thread threadb = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("b的初始值"+demo.getB());
                demo.changeB();
                System.out.println("--b更新后值"+demo.getB());
            }
        });
        //线程跑起来
        threada.start();
        threadb.start();
    }
}

结果截图:


发现a,b基本是无时间差的先后进行,3s后也是基本无时间差的先后结束。

二、反向验证一下:

将Demo类changB方法持有的锁也改成a;(两个同步代码块持同一对象锁)

    public void changeA() {
        //加锁a
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "进入同步代码块的时间:" + System.currentTimeMillis());
            a.setId(3);
            //为了观察明显,线程持锁跑3s
            try {
                Thread.sleep(3000);
            } catch (Exception e) {

            }
            System.out.println(Thread.currentThread().getName() + "退出代码块的时间:" + System.currentTimeMillis());
        }
    }

    public void changeB() {
        //加锁b
        synchronized (a) {
            System.out.println(Thread.currentThread().getName() + "进入同步代码块的时间:" + System.currentTimeMillis());
            b.setId(4);
            //为了观察明显,线程持锁跑3s
            try {
                Thread.sleep(3000);
            } catch (Exception e) {

            }
            System.out.println(Thread.currentThread().getName() + "退出代码块的时间:" + System.currentTimeMillis());
        }
    }

验证结果:


Thread0执行3秒完后,Thread1才执行,也花费3秒。





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值