不同锁互不影响,共用一个锁,可能会发生阻塞。
1.在修饰静态方法时,锁定的是当前类的 Class 对象,在下面的例子中就是SycTest1.class
2.当修饰非静态方法时,锁定的就是 this 对象,即当前的实例化对象
public class SyncTest1 {// synchronized修饰非静态方法public synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// synchronized修饰this对象,即当前的实例化对象public void test2() {synchronized (this) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {t1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
通过上面代码中可以看到,在test1里修饰的是非静态方法,即锁定的为当前实例化对象,即对象锁,test2锁定的就是this对象,也是对象锁,也就是thread1和thread2请求的是同一把锁,所以是Thread1运行完之后Thread2才运行。
public class SyncTest1 {// 修饰静态方法public static synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// 修饰类对象public void test2() {synchronized (SyncTest1.class) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {SyncTest1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
通过上面代码中可以看到,在test1里修饰的是静态方法,即锁定的为当前的类对象,即类锁,而test2锁定的SyncTest1.class,也是类锁,也就是thread1和thread2请求的是同一把锁,所以是Thread1运行完之后Thread2才运行。
public class SyncTest1 {// 修饰静态方法public static synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// 修饰非静态方法public synchronized void test2() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {SyncTest1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4
通过上面代码中可以看到,在test1里修饰的是静态方法,即锁定的为当前的类对象,即类锁,而test2锁定的非静态方法,也就是对象锁,也就是thread1和thread2请求的不是同一把锁,所以他们是两个锁,互不影响。
对象锁与类锁的区别:
对象锁和类锁其实本质上都是一种锁,区别在于一个类可以有多个对象锁,但类锁只有一个。 故使用 synchronized 对类加锁是唯一的,当一个线程拿到类锁,其他线程在执行到任何需要类锁的方法时都将阻塞。 总体来说类锁具有唯一性。
类的实例化对象可以有多个,对每个实例化对象加锁是互不干扰的,它们不具备全局唯一性,这里我们称它为对象锁。
对象锁一般可以用于细粒度锁的创建。
借鉴:Java并发编程-类锁与对象锁剖析 - 掘金
synchronized的对象锁和类锁的区别 - 掘金
近日总结:感冒了......emo......