现在的位置: 首页 > 编程技术 > Java > 正文

Java synchronized到底锁住的是什么

2014年12月10日 Java ⁄ 共 4174字 ⁄ 字号 Java synchronized到底锁住的是什么已关闭评论 ⁄ 阅读 399 次

先看一段代码:

import java.util.concurrent.TimeUnit;

public class SyncDemo {
	String o = new String("a");
	String suo = new String("b");

	public static void main(String[] args) {		
		final SyncDemo sd = new SyncDemo();
		new Thread() {
			public void run() {
			sd.f();
			}
		}.start();
		new Thread() {
			public void run() {
				sd.g();
			}
		}.start();		
		sd.h();
	}

	public void f() {
		o=o+5;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in f() "+o);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				o=o+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in f() " + i+"   "+o);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void g() {
		o=o+6;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in g() "+o);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				o=o+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in g() " + i+"   "+o);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void h() {
		o=o+7;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in h() "+o);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				o=o+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in h() " + i+"   "+o);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

输出结果为:

Thread-0:not synchronized in f() a57
Thread-0:synchronized in f() 0   a5760
Thread-1:not synchronized in g() a576
main:not synchronized in h() a57
Thread-0:synchronized in f() 1   a57601
Thread-0:synchronized in f() 2   a576012
Thread-0:synchronized in f() 3   a5760123
Thread-0:synchronized in f() 4   a57601234
main:synchronized in h() 0   a576012340
main:synchronized in h() 1   a5760123401
main:synchronized in h() 2   a57601234012
main:synchronized in h() 3   a576012340123
main:synchronized in h() 4   a5760123401234
Thread-1:synchronized in g() 0   a57601234012340
Thread-1:synchronized in g() 1   a576012340123401
Thread-1:synchronized in g() 2   a5760123401234012
Thread-1:synchronized in g() 3   a57601234012340123
Thread-1:synchronized in g() 4   a576012340123401234

分析:首先java锁住的是synchronized的括号里的变量,即suo。该变量在不改变的情况下,上面的三段代码是排斥的,必须顺序完成。java锁住的并不是synchronized的代码块里的单个变量(如o),所以这个变量o还是可以在非synchronized (suo)的代码块里进行任意的改变。
再看一个例子:(即将o全部变为suo)看看变化如何。

import java.util.concurrent.TimeUnit;

public class SyncDemo {
//	String suo = new String("a");
	String suo = new String("b");

	public static void main(String[] args) {		
		final SyncDemo sd = new SyncDemo();
		new Thread() {
			public void run() {
			sd.f();
			}
		}.start();
		new Thread() {
			public void run() {
				sd.g();
			}
		}.start();		
		sd.h();
	}

	public void f() {
		suo=suo+5;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in f() "+suo);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				suo=suo+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in f() " + i+"   "+suo);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void g() {
		suo=suo+6;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in g() "+suo);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				suo=suo+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in g() " + i+"   "+suo);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public void h() {
		suo=suo+7;
		System.out.println(Thread.currentThread().getName()+ ":not synchronized in h() "+suo);
		synchronized (suo) {
			for (int i = 0; i < 5; i++) {
				suo=suo+i;
				System.out.println(Thread.currentThread().getName()+ ":synchronized in h() " + i+"   "+suo);
				try {
					TimeUnit.SECONDS.sleep(3);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

输出结果:

Thread-0:not synchronized in f() b5
main:not synchronized in h() b57
Thread-1:not synchronized in g() b576
Thread-1:synchronized in g() 0   b576000
Thread-0:synchronized in f() 0   b5760
main:synchronized in h() 0   b576000
Thread-0:synchronized in f() 1   b5760001
main:synchronized in h() 1   b5760001
Thread-1:synchronized in g() 1   b5760001
Thread-0:synchronized in f() 2   b57600012
main:synchronized in h() 2   b576000122
Thread-1:synchronized in g() 2   b5760001222
Thread-0:synchronized in f() 3   b57600012223
main:synchronized in h() 3   b576000122233
Thread-1:synchronized in g() 3   b5760001222333
Thread-0:synchronized in f() 4   b57600012223334
main:synchronized in h() 4   b576000122233344
Thread-1:synchronized in g() 4   b5760001222333444

根据上面的结果我们在用synchronized的时候最好自建一个变量,并且保证其不会改变。并将自己希望能够顺序访问的数据的代码加入到synchronized代码块中。对于synchronized同一个对象的代码块的执行顺序是互斥的并且我们也可以看出synchronized括号中的变量的改变会导致synchronized的失效,并且suo=suo+i和println的执行顺序是完全无关的。

最后这个文章不错,推荐大家可以看下:http://zhangjunhd.blog.51cto.com/113473/70300

抱歉!评论已关闭.