同步静态方法快速到底
synchronized 还可以应用在静态方法上,如果这么写,则代表的是对当前 .java 文件对应的 Class 类加锁。
Demo(注意一下 printC() 并不是一个静态方法)
class ThreadDomain
{
public synchronized 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();
}
}
public synchronized static void printB()
{
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printB()方法");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printB()方法");
}
public synchronized void printC()
{
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "进入printC()方法");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在" + System.currentTimeMillis() + "离开printC()方法");
}
}
class MyThread_0 extends Thread
{
public void run()
{
ThreadDomain.printA();
}
}
class MyThread_1 extends Thread
{
public void run()
{
ThreadDomain.printB();
}
}
class MyThread_2 extends Thread
{
private ThreadDomain td;
public MyThread_2(ThreadDomain td)
{
this.td = td;
}
public void run()
{
td.printC();
}
}
public class ThreadTest
{
public static void main(String[] args)
{
ThreadDomain td = new ThreadDomain();
MyThread_0 mt0 = new MyThread_0();
MyThread_1 mt1 = new MyThread_1();
MyThread_2 mt2 = new MyThread_2(td);
mt0.start();
mt1.start();
mt2.start();
}
}
运行结果
线程名称为:Thread-0 在1524535750225进入 printA()方法
线程名称为:Thread-2 在1524535750225进入 printC()方法
线程名称为:Thread-2 在1524535750225离开 printC()方法
// 注意:在这里有 3 秒停顿
线程名称为:Thread-0 在1524535753225离开 printA()方法
线程名称为:Thread-1 在1524535753225进入 printB()方法
线程名称为:Thread-1 在1524535753225离开 printB()方法
从运行结果来,对 printC() 方法的调用和对 printA() 方法、printB() 方法的调用时是异步的,这说明了静态同步方法和非静态同步方法持有的是不同的锁,前者是类锁,后者是对象锁。
所谓类锁,举个再具体的例子。假如一个类中有一个静态同步方法 A,new 出了两个类的实例 B 和实例 C,线程 D 持有实例 B,线程 E 持有实例 C,只要线程 D 调用了 A 方法,那么线程 E 调用 A 方法必须等待线程 D 执行完 A 方法,尽管两个线程持有的是不同的对象。