对象锁和类锁的区别 | 您所在的位置:网站首页 › java对象和类的区别 › 对象锁和类锁的区别 |
一、对象锁
对象锁,顾名思义是锁住对象,不同实例的锁互不影响。 对象锁有两种加锁的方式,主要却在于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 实验室设备网 版权所有 |