synchronized可以修饰代码块和方法,方法又分为静态方法和普通方法,那么一言概之:线程执行的时候当有synchronized时,他获取的是类锁或实例锁然后才能执行。
代码准备:
构造四类同步方法:
public synchronized void a() { System.out.println("a"); try { Thread.sleep(10000l); } catch (InterruptedException e) { e.printStackTrace(); }}public synchronized void b() { System.out.println("b");}public static synchronized void c() { System.out.println("static c"); try { Thread.sleep(10000l); } catch (InterruptedException e) { e.printStackTrace(); }}public static synchronized void d() { System.out.println("static d");}
通过sleep来实现操作差
案例1:如果某一对象有多个同步方法,那么其只能排队访问其对应的同步方法,因为此时是对象锁
public static void testInstance1() { final ThreadTest t1 = new ThreadTest(); new Thread(new Runnable() { @Override public void run() { t1.a(); } }, "T1").start(); new Thread(new Runnable() { @Override public void run() { t1.b(); } }, "T2").start();}
输出:
a
然后开始等待,方法a执行完之后输出b
案例2:多个实例,访问各自不同的同步方法时不受影响:
public static void testInstance2() { final ThreadTest t1 = new ThreadTest(); final ThreadTest t2 = new ThreadTest(); new Thread(new Runnable() { @Override public void run() { t1.a(); } }, "T1").start(); new Thread(new Runnable() { @Override public void run() { t2.b(); } }, "T2").start();}
输出:
a
b
方法a未执行结束
案例3:当同步访问静态方法和非静态方法时不受影响,因为他们是两个不同的锁,静态方法是类锁而非静态方法为实例锁:
public static void testInstance3() { final ThreadTest t1 = new ThreadTest(); new Thread(new Runnable() { @Override public void run() { t1.a(); } }, "T1").start(); new Thread(new Runnable() { @Override public void run() { ThreadTest.c(); } }, "T2").start();}
输出:
a
static c
而a方法未执行结束,实例锁未释放
案例4:当并发访问两个非静态方法是需要同步等待:
public static void testInstance4() { new Thread(new Runnable() { @Override public void run() { ThreadTest.c(); } }, "T2").start(); new Thread(new Runnable() { @Override public void run() { ThreadTest.d(); } }, "T1").start();}
输出:
static c
等c执行完成之后释放了类锁之后输出static d
结论:
1.静态方法锁的是类,而非静态方法锁的是当前的实例,两把不同的锁互不影响;2.类锁只有一把,而不同的实例其锁不同;3.静态代码块效果等同;