Synchronized 和 static synchronized 的区别

问题:static 修饰的Synchronized 方法和非 static Synchronized 方法区别?

 这个问题是一个同事在一次无意间中问过我的;在解释之前,我们先来看两个demo;我觉得通过代码来讲解释最容易理解的:

demo1:

/**
 * 
 * @author leo-zeng
 *
 */
public class SynchronizedDemo {

	public static synchronized void staticTest() {
		for (int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);
				System.out.println("static test"+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	public synchronized void test() {
		for (int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);
				System.out.println(" test"+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		//SynchronizedDemo 类的两个实例
		final SynchronizedDemo d1 = new SynchronizedDemo();
		final SynchronizedDemo d2 = new SynchronizedDemo();
		//线程1
		Thread thread1 = new Thread(new Runnable() {

			public void run() {
				d1.test();
			}
		}, "a");
		//线程2
		Thread thread2 = new Thread(new Runnable() {

			public void run() {
				d2.test();
			}
		}, "b");
		thread1.start();
		thread2.start();
	}
}
demo1 得到的结果是:

 testa
 testb
 testa
 testb
 testa
 testb
 testa
 testb
 testa
 testb

发现Synchronized 对于本例中并没有起作用;

再看看demo2:

/**
 * 
 * @author leo-zeng
 *
 */
public class StaticSynchronizedDemo {

	public static synchronized void staticTest() {
		for (int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);
				System.out.println("static test"+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

	}

	public synchronized void test() {
		for (int i = 0; i < 5; i++) {
			try {
				Thread.sleep(1000);
				System.out.println(" test"+Thread.currentThread().getName());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		final StaticSynchronizedDemo d1 = new StaticSynchronizedDemo();
		final StaticSynchronizedDemo d2 = new StaticSynchronizedDemo();

		Thread thread1 = new Thread(new Runnable() {

			public void run() {
				StaticSynchronizedDemo.staticTest();
			}
		}, "b");

		Thread thread2 = new Thread(new Runnable() {

			public void run() {
				StaticSynchronizedDemo.staticTest();
			}
		}, "a");
		thread1.start();
		thread2.start();
	}
}
得到的结果:
static testb
static testb
static testb
static testb
static testb
static testa
static testa
static testa
static testa
static testa

发现 两个线程被Synchronized 加上说了;线程同步走了; 为什么会这样呢;其实从两个例子就很好的回答了上面那个问题。

 synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,记住看好了是该类的”当前实例“;demo1中 我们线程调用的是类的不同实例,所以synchronized对类的不同实例没有约束。再看看demo2;static synchronized恰好就是要控制类的所有实例的访问了,static synchronized是限制线程同时访问jvm中该类的所有实例同时访问对应的代码快。实际上,在类中某方法或某代码块中有 synchronized,那么在生成一个该类实例后,改类也就有一个监视快,放置线程并发访问改实例synchronized保护块,而static synchronized则是所有该类的实例公用一个监视快了,也也就是两个的区别了;可以总结说:synchronized 是 this.synchronized;而static synchronized 是类的synchronized;

拓展:

看下demo3

public class SynchronizedDemo3 {
	private final static Integer lock = new Integer(0);
	/**
	 * 静态方法
	 */
	public static void staticTest(){
		//锁住lock 对象
		synchronized (lock) {
			for (int i = 0; i < 3; i++) {
				try {
					Thread.sleep(1000);
					System.out.println(" static test"+Thread.currentThread().getName());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public  void test(){
		synchronized (lock) {
			for (int i = 0; i < 3; i++) {
				try {
					Thread.sleep(1000);
					System.out.println(" test"+Thread.currentThread().getName());
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void main(String[] args) {
		final SynchronizedDemo3 s1 =new SynchronizedDemo3();
		final SynchronizedDemo3 s2 =new SynchronizedDemo3();
		
		Thread thread1 = new Thread(new Runnable() {

			public void run() {
				SynchronizedDemo3.staticTest();
			}
		}, "b");

		Thread thread2 = new Thread(new Runnable() {

			public void run() {
				s1.test();
			}
		}, "a");
		Thread thread3 = new Thread(new Runnable() {

			public void run() {
				s2.test();
			}
		}, "c");
		thread1.start();
		thread2.start();
		thread3.start();
	}
}
得到的结果就是 

 static testb
 static testb
 static testb
 testc
 testc
 testc
 testa
 testa
 testa

因为Syssynchronized (lock) ;加在同一个object 对象上;所以就确保了类的所有对象都能约束到了。

y

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值