1 简介synchronized
Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然可以访问该object中的非加锁代码块。
参考 http://baike.baidu.com/link?url=G_bdTHKHwX6gcAYNC167sfklp0D4BmcIVnae-MQIn5_PErYpGU2SiGEfeDunGkViGbFDcWPmioElk8KLX3i0La
2 关于公平性,是否公平锁。
测试结果
A jdk1.5是不公平,但是线程数较少的时候,会看起来公平,而且不公平性没有1.6表现的明显。
B jdk1.6是不公平的,因为底层实现主要依靠Lock-Free的队列,基本思路是自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲了公平性,但获得了高吞吐量。
测试代码
1 public class MainC 2 { 3 public static void main(String[] args) 4 { 5 System.out.println("6 start"); 6 MainC tc = new MainC(); 7 for (int i = 0; i < 10; i++) 8 { 9 Thread1 t1 = tc.new Thread1(tc,i); 10 t1.start(); 11 } 12 13 } 14 class Thread1 extends Thread 15 { 16 MainC tc = null; 17 int i=0; 18 19 public Thread1(MainC tc,int i) 20 { 21 this.tc = tc; 22 this.i = i; 23 } 24 25 @Override 26 public void run() 27 { 28 tc.method1(i); 29 } 30 } 31 public synchronized void method1(int i) 32 { 33 System.out.println("method:" + i); 34 try 35 { 36 Thread.sleep(1000); 37 } 38 catch (InterruptedException e) 39 { 40 e.printStackTrace(); 41 } 42 43 } 44 }
执行结果
Jdk1.5:
5 start
method:0
method:1
method:2
method:3
method:4
method:5
method:6
method:7
method:8
method:9
Jdk1.6:
6 start
method:0
method:9
method:5
method:8
method:7
method:6
method:4
method:3
method:2
method:1
3 耗时测试
a 本地4G内存 +3.2GHZ CPU+32位win7系统
b 测试结果
在多线程情况下,jdk1.5较耗时。
在多线程情况下,jdk1.6耗时比较稳定,而且比较低。
测试代码:
public class MainC { static class SynRunner implements Runnable { private long v = 0; public synchronized void run() { v = v + 1; } } static class LockRunner implements Runnable { private ReentrantLock lock = new ReentrantLock(); private long v = 0; public void run() { lock.lock(); try { v = v + 1; } finally { lock.unlock(); } } } static class Tester { private AtomicLong runCount = new AtomicLong(0); private AtomicLong start = new AtomicLong(); private AtomicLong end = new AtomicLong(); public Tester(final Runnable runner, int threadCount) { final ExecutorService pool = Executors.newFixedThreadPool(threadCount); Runnable task = new Runnable() { public void run() { while (true) { runner.run(); long count = runCount.incrementAndGet(); if (count == 1) { start.set(System.nanoTime()); } else if (count >= 10000000) { if (count == 10000000) { end.set(System.nanoTime()); System.out.println(runner.getClass().getSimpleName() + ", cost: " + (end.longValue()-start.longValue())/1000000 + "ms"); } pool.shutdown(); return; } } } }; for (int i = 0; i < threadCount; i++) { pool.submit(task); } } } public static void main(String[] args) { System.out.println("jdk6"); new Tester(new SynRunner(), 30); //new Tester(new LockRunner(), 10); } }
Synchronized 测试结果
线程数 |
1 |
10 |
30 |
50 |
100 |
Jdk1.5 |
jdk5 SynRunner, cost: 335ms
|
jdk5 SynRunner, cost: 22419ms
|
jdk5 SynRunner, cost: 22597ms
|
jdk5 SynRunner, cost: 22715ms
|
jdk5 SynRunner, cost: 22868ms
|
Jdk1.6 |
jdk6 SynRunner, cost: 323ms |
jdk6 SynRunner, cost: 1679ms
|
jdk6 SynRunner, cost: 1766ms
|
jdk6 SynRunner, cost: 1713ms
|
jdk6 SynRunner, cost: 1740ms
|