前提,synchronized 加到 static 方法前面是给class 加锁,即类锁;而synchronized 加到非静态方法前面是给对象上锁。
对象锁和类锁是不同的锁,所以多个线程同时执行这2个不同锁的方法时,是异步的。
在LockTask类中定义三个方法,task1方法和task2方法为类锁,task3方法为对象锁。
class LockTask {
public synchronized static void task1() {
System.out.println(Thread.currentThread().getName() + "start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "end");
}
public synchronized static void task2() {
System.out.println(Thread.currentThread().getName() + "start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "end");
}
public synchronized void task3() {
System.out.println(Thread.currentThread().getName() + "start");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "end");
}
}
创建三个线程类,分别执行task1,task2,task3:
static class Thread1 extends Thread {
LockTask lockTask;
public Thread1(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task1();
}
}
static class Thread2 extends Thread {
LockTask lockTask;
public Thread2(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task2();
}
}
static class Thread3 extends Thread {
LockTask lockTask;
public Thread3(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task3();
}
}
创建三个线程,执行同一个lockTask对象的三个方法:
public static void main(String[] args) {
LockTask lockTask = new LockTask();
Thread1 thread1 = new Thread1(lockTask);
Thread2 thread2 = new Thread2(lockTask);
Thread3 thread3 = new Thread3(lockTask);
thread1.setName("thread1");
thread2.setName("thread2");
thread3.setName("thread3");
thread1.start();
thread2.start();
thread3.start();
}
执行顺序为:

因为task1和task2方法都是类锁,所以多线程执行方法执行同一个类锁,所以task1和task2方法是同步执行的,task3与task1、task2是异步执行的。
修改示例改为使用对象锁:
class LockTaskTest2 {
static class Thread1 extends Thread {
LockTask lockTask;
public Thread1(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task3();
}
}
static class Thread2 extends Thread {
LockTask lockTask;
public Thread2(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task3();
}
}
public static void main(String[] args) {
LockTask lockTask = new LockTask();
LockTask lockTask2 = new LockTask();
Thread1 thread1 = new Thread1(lockTask);
Thread2 thread2 = new Thread2(lockTask2);
thread1.setName("thread1");
thread2.setName("thread2");
thread1.start();
thread2.start();
}
}
执行结果:

两个线程执行task3方法,为对象锁方法,只会锁住同一对象,lockTask与lockTask2为不同对象,所以会异步执行。
修改示例改为多线程使用类锁,只将执行task3方法改为task1方法:
class LockTaskTest2 {
static class Thread1 extends Thread {
LockTask lockTask;
public Thread1(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task1();
}
}
static class Thread2 extends Thread {
LockTask lockTask;
public Thread2(LockTask lockTask) {
this.lockTask = lockTask;
}
@Override
public void run() {
lockTask.task1();
}
}
public static void main(String[] args) {
LockTask lockTask = new LockTask();
LockTask lockTask2 = new LockTask();
Thread1 thread1 = new Thread1(lockTask);
Thread2 thread2 = new Thread2(lockTask2);
thread1.setName("thread1");
thread2.setName("thread2");
thread1.start();
thread2.start();
}
}
执行结果:

两个线程执行task1方法,为类锁方法,lockTask与lockTask2虽然为不同对象,但是类锁对该类所有对象都起加锁作用,thread1拿到LockTask类锁,执行完task1方法,thread2才能拿到类锁执行task1方法,所以会同步执行。
总结:
1.如果多线程同时访问同一类的类锁以及对象锁,这两个方法执行是异步的,原因:类锁和对象锁是2中不同的锁,可以各自持有锁。
2.类锁对该类的所有对象都能起作用,而对象锁对该类不同对象不起作用。
网友评论