synchronized 测试

       写过多线程的人   对synchronized这个关键字肯定很熟悉。我记得去年面试的时候,有一次二面就是问得它。让详细得说出它的作用,它锁的是什么东西。。   当初回答的很模糊,才知道自己了解的并不清楚。回来查资料,自己写程序测试。

        在java里,一切东西都是对象,学java的人一定要有这个概念。一切都是,java里所有类都默认继承object,你的一切代码,不是对象就是对象的动作。你操作的所有东西也都是对象,基础类型也有基本的对应的包装类,也是对象。synchronized关键字,锁住的也是对象。目前我只发现它锁的两个东西:  一个是类的实例,就是具体的对象,还有一个就是实体类(也是对象)。

       上代码:

        

package codeTest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName: ThreadTest4
 * @Description: TODO(测试synchronized)
 * @author xuejupo [email protected]
 * @date 2015-11-1 下午10:24:00
 * 
 */
public class ThreadTest4 {
	
	public static void main(String[] a) {
		long start = System.currentTimeMillis();
		ExecutorService pool = Executors.newFixedThreadPool(100);
		List<Callable<String>> tasks = new ArrayList<Callable<String>>();
		for (int i = 0; i < 100; i++) {
			synchroTest t = new synchroTest();
			tasks.add(t);
		}
		try {
			pool.invokeAll(tasks);
			pool.shutdown();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long end = System.currentTimeMillis();
		System.out.println("线程执行了" + (end - start) + "毫秒");
	}
}

class synchroTest implements Callable<String> {
	public synchronized static void test1() {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}

	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		test1();
		return null;
	}
}

     结果是:

线程执行了1009毫秒

 在上面的测试程序里,我用synchronized锁住了static方法,可以看到,100个线程也丝毫没有发挥多线程的优势。一个需要执行10毫秒的方法,100个线程用了1000多毫秒才执行完。synchronized锁住了static方法,相当于锁住了整个线程类。当第一个线程调用test1方法时,第二个线程创建了也只能等待。第一个线程执行完毕释放锁,第二个线程开始执行。。。。    其实就是个单线程工作。。   

      第二个测试程序,将线程类里test方法前的static关键字去掉,代码就不贴了,结果如下:

线程执行了22毫秒

   充分发挥了多线程的优势..  这是因为在第一个线程实例化了线程类synchroTest,申请了线程锁,他只是锁住了自己的实例t1,第二个线程实例化了线程类synchroTest,申请线程锁,他也只是锁住了自己的线程类t2.所以这个测试除了申请锁和释放锁的消耗,跟无锁的线程是没有任何区别的。

     把线程类改成这样:

class synchroTest implements Callable<String> {
	public static  Object b = new Object();
      public void test(){
    	  synchronized (b) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
      }
	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		test();
		return null;
	}
}

  

 结果:

线程执行了1009毫秒

     跟第一个测试类似,第一个线程锁住了一个static的对象b,第二个对象视图申请b的锁,因为static对象在内存中只有一份,所以第二个线程申请锁的对象b,其实跟第一个线程锁住的是同一个对象。所以他只能等待第一个对象释放锁。

     把object前的static去掉,结果是:

线程执行了21毫秒

       说明申请线程对象的时候,申请了100个不同的对象,每个不同的对象里面都申请了不一样的object对象,锁其实锁住的是不同对象里面的不同的object。

      还有个测试,说明其实锁住实例对象里面的object   跟锁住实例对象是不一样的。一个锁。假设对象A里有个对象b,那么某线程申请b的锁,对A是没有影响的,别的线程还是可以访问线程A的其他synchronized方法。

代码:

class synchroTest implements Callable<String> {
	public static Object b = new Object();
      public void test(){
    	  synchronized (b) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
      }
      public synchronized void test1(){
    	  try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
      }
	@Override
	public String call() throws Exception {
		// TODO Auto-generated method stub
		test();      //-----(1)
                test1();      //---------(2)
		return null;
	}
}

结果:

  

线程执行了1017毫秒

    分析一下:当第一个线程t1在执行(1)的时候,他将b锁住,这时候没有其他线程可以申请到b的锁,所以只有t1在执行。可是当t1执行完(1),开始执行(2)的时候,线程t2就可以申请b的锁了,所以线程t2和线程t1可以并发执行。这样的结果跟单纯执行object为static时方法test的结果类似。

猜你喜欢

转载自709002341.iteye.com/blog/2253666