类锁
public class ClassLock {
static long t1 = System.currentTimeMillis();
synchronized static void lock() {
int time = (int) Math.ceil((System.currentTimeMillis() - t1)/1000);
System.out.println(Thread.currentThread().getName()+":"+time);
SleepUtil.sleep(1000);
}
public static void main(String[] args) {
Runnable runnable = ()->{
while (true) {
ClassLock.lock();
}
};
for (int i = 0; i < 3; i++) {
new Thread(runnable).start();
}
}
}
输出:
Thread-0:0
Thread-0:1
Thread-0:2
Thread-2:3
Thread-2:4
Thread-2:5
Thread-2:6
Thread-2:7
Thread-2:8
...
可以看到,三个线程共享一把锁,一个时刻只有一个线程允许访问lock()方法。
给类的静态方法加上 synchronized 关键字修饰,就相当于给该静态方法加了一把类锁。
类锁是一个全局锁,无论多少个对象,均共享同一把锁。
等同于下面的方式:
synchronized (ClassLock.class) {
...
}
对象锁
一个对象持有一把锁,不同对象之间互不影响。
当对象为单例时,对象锁和类锁效果一样。
示例代码
public class InstanceLock {
long t1 = System.currentTimeMillis();
synchronized void lock(){
int time = (int) Math.ceil((System.currentTimeMillis() - t1)/1000);
System.out.println(Thread.currentThread().getName()+":"+time);
SleepUtil.sleep(1000);
}
private static class MyThread extends Thread{
private InstanceLock instanceLock;
public MyThread(InstanceLock instanceLock) {
this.instanceLock = instanceLock;
}
@Override
public void run() {
while (true) {
instanceLock.lock();
}
}
}
}
单实例时
public static void main(String[] args) {
InstanceLock lock = new InstanceLock();
for (int i = 0; i < 3; i++) {
new MyThread(lock).start();
}
}
输出:
Thread-0:0
Thread-1:1
Thread-2:2
Thread-0:3
Thread-2:4
...
效果和类锁一致,多个线程访问同一个对象同步方法时,只有一个线程允许访问,其他线程会被阻塞。
多实例时
public static void main(String[] args) {
//InstanceLock lock = new InstanceLock();
for (int i = 0; i < 3; i++) {
new MyThread(new InstanceLock()).start();
}
}
输出:
Thread-2:0
Thread-0:0
Thread-1:0
Thread-2:1
Thread-0:1
Thread-1:1
Thread-0:2
Thread-2:2
Thread-1:2
...
多个实例访问不同对象的同步方法,互不影响,可以同时进行。