问:谈一谈sychronized中类锁和对象锁的区别。
答:类锁和对象锁是两种不同的锁,对静态方法加锁或者使用sychronized(XX.class)相当于加了类锁,对实例方法加锁或者采用sychronized(this或对象)相当于加了对象锁,区别在于对于同一个类的不同实例来说,如果加了类锁,那么在一个线程获得类锁后,其他线程即使是持有同一个类的不同的实例,也得等待类锁的释放,因为它们竞争的都是类锁,如果一个线程获得了对象锁,那么持有不同对象的线程则可以并发执行,因为虽然竞争的都是对象锁,但并不是同意把对象锁。既然类锁和对象锁是不同的锁,那么一个线程可以同时获取两把锁。
class MyThread1 extends Thread {
private TestSychronized test;
public MyThread1(TestSychronized test) {
this.test = test;
}
@Override
public void run() {
test.fun1();
test.fun3();
}
}
class MyThread2 extends Thread {
private TestSychronized test;
public MyThread2(TestSychronized test) {
this.test = test;
}
@Override
public void run() {
test.fun2();
test.fun4();
}
}
public class TestSychronized {
static synchronized void fun1() {
System.out.println(Thread.currentThread().getName() + "静态方法锁fun1,等待2s");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static synchronized void fun2() {
System.out.println(Thread.currentThread().getName() + "静态方法锁fun2,等待2s");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized void fun3() {
System.out.println(Thread.currentThread().getName() + "实例方法锁fun3,等待2s");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized void fun4() {
System.out.println(Thread.currentThread().getName() + "实例方法锁fun4,等待2s");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TestSychronized ts1 = new TestSychronized();
TestSychronized ts2 = new TestSychronized();
MyThread1 mt1 = new MyThread1(ts1);
MyThread1 mt2 = new MyThread1(ts2);
// MyThread2 mt3 = new MyThread2(ts1);
// MyThread2 mt4 = new MyThread2(ts2);
mt1.start();
mt2.start();
// mt3.start();
// mt4.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
上面代码执行顺序的一种情况是:
Thread-0和Thread-1要竞争类锁,Thread-1拿到了,先执行,然后等待2s,执行完成释放类锁,Thread-0可以获得类锁,同时Thread-1可以获取对象锁,这两个锁不冲突,锁Thread-0:fun1和Thread-1:fun3可以并发执行,Thread-0执行完fun1后,等待2s,然后执行fun3。