一.对象锁和类锁的区别
对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。
同步控制的范围越小,并发性能越好;反之,并发性能越差。一般来说,并发性能由高到底,synchronized 代码块>synchronized 同步方法>类锁。
二.对象锁
1.对象锁只针对同一个实例对象中synchronized 修饰的部分实现同步,对同一个类下的多个对象、同一个对象的非synchronized 修饰的部分不会阻塞 。
1 public class MyObject { 2 //加对象锁 3 public synchronized void method1(){ 4 System.out.println("method1 start----"); 5 try { 6 Thread.sleep(5000); 7 } catch (InterruptedException e) { 8 e.printStackTrace(); 9 } 10 System.out.println("method1 end----"); 11 } 12 13 //加对象锁 14 public synchronized void method2(){ 15 System.out.println("method2 start----"); 16 try { 17 Thread.sleep(5000); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 System.out.println("method2 end----"); 22 } 23 24 //不加锁 25 public void method3(){ 26 System.out.println("method3 start----"); 27 try { 28 Thread.sleep(5000); 29 } catch (InterruptedException e) { 30 e.printStackTrace(); 31 } 32 System.out.println("method3 end----"); 33 } 34 }
多线程操作同一个对象synchronized 修饰的部分,一个线程必须等待前一个线程的对象锁释放之后才开始执行,线程执行顺序不确定,运行结果如下:
1 //同一个实例对象 2 final MyObject obj1=new MyObject(); 3 new Thread(new Runnable() { 4 @Override 5 public void run() { 6 obj1.method1(); 7 } 8 }).start(); 9 10 new Thread(new Runnable() { 11 @Override 12 public void run() { 13 obj1.method2(); 14 } 15 }).start();
多线程操作不同对象,对象锁无效,运行结果如下:
1 //不同实例对象 2 final MyObject obj1=new MyObject(); 3 final MyObject obj2=new MyObject(); 4 new Thread(new Runnable() { 5 @Override 6 public void run() { 7 obj1.method1(); 8 } 9 }).start(); 10 11 new Thread(new Runnable() { 12 @Override 13 public void run() { 14 obj2.method2(); 15 } 16 }).start();
多线程操作同一对象的同步方法和非同步方法,彼此之间互不影响,不会发生阻塞,运行结果如下:
1 //同一对象 2 final MyObject obj1=new MyObject(); 3 new Thread(new Runnable() { 4 @Override 5 public void run() { 6 obj1.method1(); 7 } 8 }).start(); 9 10 new Thread(new Runnable() { 11 @Override 12 public void run() { 13 obj1.method3(); 14 } 15 }).start(); 16 }
三.类锁
类锁是锁住整个类,不管有多少个对象,共用一把类锁,且类锁只有一把,不管怎么调用,都会同步。
1 //加类锁 2 public synchronized static void method4(){ 3 System.out.println(Thread.currentThread().getName()+" call method4 start----"); 4 try { 5 Thread.sleep(1000); 6 } catch (InterruptedException e) { 7 e.printStackTrace(); 8 } 9 System.out.println(Thread.currentThread().getName()+" call method4 end----"); 10 }
1 final MyObject obj1 = new MyObject(); 2 final MyObject obj2 = new MyObject(); 3 new Thread(new Runnable() { 4 @Override 5 public void run() { 6 obj1.method4(); 7 } 8 }, "thread1").start(); 9 10 new Thread(new Runnable() { 11 @Override 12 public void run() { 13 obj1.method4(); 14 } 15 }, "thread2").start(); 16 17 new Thread(new Runnable() { 18 @Override 19 public void run() { 20 obj2.method4(); 21 } 22 }, "thread3").start(); 23 }