java锁学习(二)

类锁

类锁 !!!! java类有很多对象 ,但是只有一个class对象 !!!!

所以,类锁,就是针对当前类的Class对象的锁

类锁同一时刻只能被一个对象获取

  1. synchronized放在static方法上(静态锁)
  2. synchronized放在class对象上

静态锁

class SyncClassStatic implements Runnable {
    @Override
    public void run() {
        method();
    }

    public static synchronized void method() {
        System.out.println("我是类锁中静态锁");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}
result:
我是类锁中静态锁
Thread-6运行结束
我是类锁中静态锁
Thread-7运行结束
类锁,静态锁运行完毕

class对象锁

class SyncClassObj implements Runnable{
    @Override
    public void run() {
        method();
    }

    private void method(){
        synchronized (SyncClassObj.class) {
            System.out.println("我是类锁中class对象锁");
            try{
                Thread.sleep(3000);
            }catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName()+"运行结束");
        }
    }
}
result:
我是类锁中class对象锁
Thread-8运行结束
我是类锁中class对象锁
Thread-9运行结束
类锁,class对象运行完毕

常见场景和问题

  1. 两个线程同时访问一个对象的同步方法会怎样?

    依次执行(锁住的是同一个对象)

  2. 两个线程访问的是两个对象的同步方法又会怎样?

    随机执行(锁住的是不同的对象)

  3. 两个线程访问的是synchronized的静态方法会怎样?

    依次执行(锁住的是同一个类)

  4. 同时访问同步方法与非同步方法会怎样?

    只锁加了synchronized的方法,其他方法不会收到影响

class SyncObjLock implements Runnable {


    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")) {
            syncMethod();
        }else{
            asyncMethod();
        }
    }

    private synchronized void syncMethod()
    {
        System.out.println("我被锁了");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }

    private void asyncMethod()
    {
        System.out.println("我没被锁");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}
同时开始,同时结束:
我被锁了
我没被锁
Thread-0运行结束
Thread-1运行结束
  1. 访问同一个对象的不同的普通同步方法会怎样?
class SyncDiff implements Runnable{
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")) {
            syncMethod1();
        }else{
            syncMethod2();
        }
    }


    private synchronized void syncMethod1()
    {
        System.out.println("我被锁了,我是方法1");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }


    private synchronized void syncMethod2()
    {
        System.out.println("我被锁了,我是方法2");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}
同时开始,同时结束:
我被锁了
我没被锁
Thread-0运行结束
Thread-1运行结束
  1. 同时访问静态sync和非静态sync方法
class SyncStaticOrNo implements Runnable {
    @Override
    public void run() {
        if(Thread.currentThread().getName().equals("Thread-0")) {
            syncMethod1();
        }else{
            syncMethod2();
        }
    }


    private synchronized void syncMethod1()
    {
        System.out.println("我被对象锁");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }


    private static synchronized void syncMethod2()
    {
        System.out.println("我是类锁");
        try{
            Thread.sleep(3000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println(Thread.currentThread().getName()+"运行结束");
    }
}
同时开始,同时结束:
我被锁了
我没被锁
Thread-0运行结束
Thread-1运行结束
  1. 方法抛出异常后,会释放锁吗?

会,jvm帮我们释放了

class SyncExc implements Runnable{


    @Override
    public void run() {
            method1();
    }

    private synchronized void method1()
    {
        System.out.println(Thread.currentThread().getName()+"开始");
        try{
            Thread.sleep(3000);
        }catch (Exception e) {
            e.printStackTrace();
        }
        throw new RuntimeException("");
//        System.out.println("运行结束");
    }

}
Thread-0开始
Exception in thread "Thread-0" java.lang.RuntimeException: 
	at Thread.SyncExc.method1(SynchronizedObject.java:187)
	at Thread.SyncExc.run(SynchronizedObject.java:176)
	at java.lang.Thread.run(Thread.java:748)
Thread-1开始
Exception in thread "Thread-1" java.lang.RuntimeException: 
	at Thread.SyncExc.method1(SynchronizedObject.java:187)
	at Thread.SyncExc.run(SynchronizedObject.java:176)
	at java.lang.Thread.run(Thread.java:748)

锁的使用场景及分析

整个系统全局同步用类锁,局部锁用对象锁

对比下,就像一样,锁的范围越大,性能自然越低(粒度:类锁>对象锁 性能:类锁<对象锁)

转载于:https://my.oschina.net/lwl1989/blog/3049584

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值