同步静态方法
synchronized还可以应用在静态方法上,如果这么写,则代表的是对当前.java文件对应的Class类加锁。看一下例子,注意一下printC()并不是一个静态方法:
public
class
ThreadDomain25
{ 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()方法"); } }
写三个线程分别调用这三个方法:
public class MyThread25_0 extends Thread { public void run() { ThreadDomain25.printA(); } }
public class MyThread25_1 extends Thread { public void run() { ThreadDomain25.printB(); } }
public class MyThread25_2 extends Thread { private ThreadDomain25 td; public MyThread25_2(ThreadDomain25 td) { this.td = td; } public void run() { td.printC(); } }
写个main函数启动这三个线程:
public static void main(String[] args) { ThreadDomain25 td = new ThreadDomain25(); MyThread25_0 mt0 = new MyThread25_0(); MyThread25_1 mt1 = new MyThread25_1(); MyThread25_2 mt2 = new MyThread25_2(td); mt0.start(); mt1.start(); mt2.start(); }
看一下运行结果:
线程名称为:Thread-0在1443857019710进入printA()方法 线程名称为:Thread-2在1443857019710进入printC()方法 线程名称为:Thread-2在1443857019710离开printC()方法 线程名称为:Thread-0在1443857022710离开printA()方法 线程名称为:Thread-1在1443857022710进入printsynchronized B()方法 线程名称为:Thread-1在1443857022710离开printB()方法
从运行结果来,对printC()方法的调用和对printA()方法、printB()方法的调用时异步的,这说明了静态同步方法和非静态同步方法持有的是不同的锁,前者是类锁,后者是对象锁。
所谓类锁,举个再具体的例子。假如一个类中有一个静态同步方法A,new出了两个类的实例B和实例C,线程D持有实例B,线程E持有实例C,只要线程D调用了A方法,那么线程E调用A方法必须等待线程D执行完A方法,尽管两个线程持有的是不同的对象。
同步类.Class
同步synchronized(class) 和同步静态方法都是一样,同步的都是当前的类锁
类Service
结果
实验证明 静态方法 和静态类.class 锁 都是一样获取的类锁
数据String的常量池特性
在使用同步的时候,如果要锁定String , 两个线程运行的时候,很可能有一个无限等待无法获取到锁
这里就是String 常量池带来的奇葩问题 , 要特别注意