public class Sync { public synchronized void test() { System.out.println("test start"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test end"); } }
#html
public class MyThread extends Thread{ public void run() { Sync sync = new Sync(); sync.test(); } public static void main(String[] args) { for (int i = 0; i < 3; ++i) { Thread thread = new MyThread(); thread.start(); } } }
执行结果程序员
test start test start test start test end test end test end
现象swift
在MyThread中,每次都new一个新的Sync对象,能够看到代码块test虽然被加了synchonized可是仍是并行执行的,初步结论:锁住的不是代码块安全
public class MyThread2 extends Thread{ public Sync sync; MyThread2(Sync sync) { this.sync = sync; } public void run() { System.out.println("hi...."); sync.test(); } public static void main(String[] args) { Sync sync = new Sync(); for (int i = 0; i < 3; ++i) { Thread thread = new MyThread2(sync); thread.start(); } }
执行结果bash
hi.... test start hi.... hi.... test end test start test end test start test end
现象并发
能够看到当他们共用一个对象的时候,synchonized起了做用,这块代码是串行执行的性能
锁住的是对象this
解决也很简单,只要锁住同一个对象就好了。例如:synchronized后的括号中锁同一个固定对象,这样就好了。spa
这样是没问题,可是,比较多的作法是让synchronized锁这个类对应的Class对象。.net
public class Sync2 { public void test() { synchronized (Sync2.class) { System.out.println("test start"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("test end"); } } }
#
public class MyThread3 extends Thread{ public void run() { Sync2 sync = new Sync2(); sync.test(); } public static void main(String[] args) { for (int i = 0; i < 3; ++i) { Thread thread = new MyThread3(); thread.start(); } } }
执行结果
test start
test end
test start
test end
test start
test end
虽然synchronized已经做为一个关键字被固化在Java语言中了,但它只提供了一种至关保守的线程安全策略,且该策略开放给程序员的控制能力极弱