对象锁和类锁的区别

一、对象锁

对象锁,顾名思义是锁住对象,不同实例的锁互不影响。
对象锁有两种加锁的方式,主要却在于Synchronized作用的地方的不同
1.作用在实例方法上

public synchronized void method(){}

2.作用在代码块上

public void method(){
   synchronized(this){
   //这里是需要同步的部分
 }
}

持有相同对象锁的地方会出现互斥:

 public synchronized  void method1(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了对象锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public synchronized  void method2(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了对象锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     public static void main(String[] args) {
        SynchronizedTest test1=new SynchronizedTest();
        SynchronizedTest test2=new SynchronizedTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.method1();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.method2();
            }
        }).start();
    }

执行结果:

Thread-0持有了对象锁
Thread-0持有了对象锁
Thread-0持有了对象锁
Thread-0持有了对象锁
Thread-0持有了对象锁
Thread-0持有了对象锁
Thread-0持有了对象锁

这里的运行结果实际上陷入了死循环。因为我设置了while(ture),可以看到,Thread-0持有了当前对象的锁之后,就会排斥持有相同对象锁的线程。
synchronized修饰在实例方法上,代表着这里锁的是当前对象this.

那么对于不同的对象,将不会产生相互影响:


    public static void main(String[] args) {
        SynchronizedTest test1=new SynchronizedTest();
        SynchronizedTest test2=new SynchronizedTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.method1();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test2.method2();//调用不同对象的方法
            }
        }).start();
    }

运行结果:

Thread-0持有了对象锁
Thread-1持有了对象锁
Thread-0持有了对象锁
Thread-1持有了对象锁
Thread-0持有了对象锁
Thread-1持有了对象锁

可以看到持有不同对象锁的线程互不影响。

synchronized(object){}的效果和在实例方法上加锁一样,不同的是可以在()里添加不同的对象,例如:

synchronized(object1){}
synchronized(object2){}

当括号里的对象是一样时,表示持有的是同一对象锁,反之,就不是同一对象锁,那么线程调用时互不干扰。
synchronized(object){}()中的对象与实例方法上锁的是同一对象,那么将会互斥。例如:

public synchronized void method(){}
public void method(){
   synchronized(this){
   //这里是需要同步的部分
 }

这里,都代表锁的是当前类的对象,所持有的锁是同一把。

二、类锁

不管多少对象都共用同一把锁,同步执行,一个线程执行结束、其他的才能够调用同步的部分
也是有两种不同的加锁方式。不同的类锁互不影响
1.用synchronized修饰静态方法

public synchronized static void method()

2.作用在代码块上

public void method(){
   synchronized(object.class){
   }
}

当持有类锁时,所有实例调用这个方法上都会互相排斥。

 public synchronized static void staticMethod1(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了类锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public synchronized static void staticMethod2(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了类锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     public static void main(String[] args) {
        SynchronizedTest test1=new SynchronizedTest();
        SynchronizedTest test2=new SynchronizedTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.staticMethod1();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test2.staticMethod2();
            }
        }).start();
    }

运行结果:

Thread-0持有了类锁
Thread-0持有了类锁
Thread-0持有了类锁
Thread-0持有了类锁
Thread-0持有了类锁
Thread-0持有了类锁

可以看到,虽说调用的是不同对象的同步方法,但还是产生了互斥。

对象锁和类锁会互斥吗?

//对象锁
public synchronized  void method1(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了对象锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    //类锁
     public synchronized static void staticMethod1(){
        while (true){
            System.out.println(Thread.currentThread().getName()+"持有了类锁");
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 new Thread(new Runnable() {
            @Override
            public void run() {
                test1.method1();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test1.staticMethod1();
            }
        }).start();
    }

运行结果:

Thread-0持有了对象锁
Thread-1持有了类锁
Thread-0持有了对象锁
Thread-1持有了类锁
Thread-0持有了对象锁
Thread-1持有了类锁

可以看到对象锁和类锁互不影响。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值