对象锁和类锁的区别

您所在的位置:网站首页 java对象和类的区别 对象锁和类锁的区别

对象锁和类锁的区别

2023-12-10 08:29| 来源: 网络整理| 查看: 265

一、对象锁

对象锁,顾名思义是锁住对象,不同实例的锁互不影响。 对象锁有两种加锁的方式,主要却在于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持有了类锁

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



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3