参考:Java对象锁和类锁全面解析
参考:Synchronized同步静态方法和非静态方法总结
参考图书:《Java多线程编程核心技术 》 作者:高洪岩
很遗憾,我没有能找到synchronized修饰static方法的实际应用,哪怕是在哪个大型开源框架中用到也好。直接上结论:
- synchronized修饰非静态方法,实际上是对调用该方法的对象加锁,俗称“对象锁”。
- synchronized修饰静态方法,实际上是对该类对象加锁,俗称“类锁”。
关于synchronized 修饰静态方法的情况,我们直接看代码实例:
public class Run {
public static void main(String[] args) {
ThreadA a = new ThreadA();
a.setName("A");
a.start();
ThreadB b = new ThreadB();
b.setName("B");
b.start();
}
}
class Service {
synchronized public static void printA() {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public static void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
}
}
class ThreadA extends Thread {
@Override
public void run() {
Service.printA();
}
}
class ThreadB extends Thread {
@Override
public void run() {
Service.printB();
}
}
运行结果:
线程名称为:A在1466149372909进入printA
线程名称为:A在1466149375920离开printA
线程名称为:B在1466149375920进入printB
线程名称为:B在1466149375920离开printB
两个线程在争夺同一个类锁,因此同步
- synchronized (class)
对上面Service类代码修改成如下:
class Service {
public static void printA() {
synchronized (Service.class) {
try {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printA");
Thread.sleep(3000);
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printA");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void printB() {
synchronized (Service.class) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}
运行结果:
线程名称为:A在1466149372909进入printA
线程名称为:A在1466149375920离开printA
线程名称为:B在1466149375920进入printB
线程名称为:B在1466149375920离开printB
两个线程依旧在争夺同一个类锁,因此同步
问题:关键字synchronized修饰static方法,很少见,在哪里用到了?