Java - 并发编程:同步方法的锁对象与锁竞争

并发编程:同步方法的锁对象与锁竞争

1 示例描述

示例:定义线程任务类如下所示:

public class SynObj {

    public synchronized void showA(){          
        System.out.println("showA..");
        try {
            Thread.sleep(3000);        
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void showB(){
        synchronized (this) {
            System.out.println("showB..");
        }
    }

    public static synchronized void showC(){
        System.out.println("showC..");
        try {
            Thread.sleep(3000);        
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void showD() {      
        synchronized (SynObj.class) {
            System.out.println("showD..");
        }
    }

    public void showE() {
        System.out.println("showE..");
    }
}

思考不同方法调用情境下的锁竞争情况。

2 同步方法的锁对象

观察以下示例代码:

public class Test {
    public static void main(String[] args) {
        final SynObj sy = new SynObj();

        new Thread(new Runnable() {
            @Override
            public void run() {
                sy.showA();
            }
        }).start();

		new Thread(new Runnable() {
            @Override
            public void run() {
                sy.showB();        
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                sy.showE();
            }
        }).start();
	}
}

程序运行输出:

showA..
showE..
showB..		//延时约3秒后输出

synchronized 关键字修饰的 同步方法 的锁对象是实例对象本身。 线程A抢到时间片后执行 showA() 方法,在方法体内执行 sleep() 方法休眠但不释放锁。而线程B执行 showB() 方法中的同步代码块使用的锁对象是 this 引用,也就是执行线程任务的实例对象本身。所以在线程A睡眠时,线程B由于无法拿到锁而阻塞。期间线程E抢得CPU执行权后得以继续执行任务,而线程B则要等待线程A执行完毕释放锁对象后才能继续执行。

3 静态同步方法的锁对象

观察以下示例代码:

public class Test {
    public static void main(String[] args) {
        final SynObj sy = new SynObj();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                SynObj.showC();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                sy.showD();
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                sy.showE();
            }
        }).start();
    }
}

程序运行输出:

showC..
showE..
showD..		//延时约3秒后输出

synchronized 关键字修饰的 静态同步方法 的锁对象是类对象(class)。 线程C抢到时间片后执行 showC() 方法,在方法体内执行 sleep() 方法休眠但不释放锁。而线程D执行 showD() 方法中的同步代码块使用的锁对象是 类名.class 引用,也就是执行线程任务的类对象。所以在线程C睡眠时,线程D由于无法拿到锁而阻塞。期间线程E抢得CPU执行权后得以继续执行任务,而线程D则要等待线程C执行完毕释放锁对象后才能继续执行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值