问题一:
class ThreadTest extends Thread {
	Integer counter = 0;

	public void run() {
		synchronized (counter) {
			for (int i = 0; i < 10; i++) {
				++counter;
				System.out.println(Thread.currentThread().getName() + " "
						+ counter);
				try {
					Thread.sleep(1000);
				} catch (Exception e) {

				}
			}
		}
	}

	public static void main(String args[]) {
		Thread t1 = new ThreadTest();
		Thread t2 = new ThreadTest();
		t1.start();
		t2.start();
		try{
			t1.join();
			t2.join();
		} catch (Exception e){
			
		}
	}
}

结果(运行多次,始终是这个结果):
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-1 1
Thread-1 2
Thread-1 3
Thread-1 4
Thread-1 5
Thread-1 6
Thread-1 7
Thread-1 8
Thread-1 9
Thread-1 10
我的理解:
我创建了两个Thread instances, 每个instance有自己的instance variable counter(Integer类型),我认为虽然run里面对counter object进行了同步,但是每个instance拥有自己的counter object,不干扰,所以其实同步没有什么作用。但实际的结果是thread0做完了,thread再做,请问为什么?

问题二:
class ThreadTest extends Thread {
	static Integer counter = 0;

	public void run() {
		synchronized (counter) {
			for (int i = 0; i < 10; i++) {
				++counter;
				System.out.println(Thread.currentThread().getName() + " "
						+ counter);
				try {
					Thread.sleep(1000);
				} catch (Exception e) {

				}
			}
		}
	}

	public static void main(String args[]) {
		Thread t1 = new ThreadTest();
		Thread t2 = new ThreadTest();
		t1.start();
		t2.start();
		try{
			t1.join();
			t2.join();
		} catch (Exception e){
			
		}
		
		System.out.println(ThreadTest.counter);
	}
}

结果(不唯一,很多种):
Thread-0 2
Thread-1 2
Thread-0 3
Thread-1 3
Thread-0 5
Thread-1 5
Thread-1 6
Thread-0 7
Thread-1 8
Thread-0 8
Thread-1 10
Thread-0 10
Thread-0 12
Thread-1 12
Thread-1 14
Thread-0 14
Thread-1 15
Thread-0 16
Thread-0 18
Thread-1 18
18
我的理解:
问题二中代码与问题一代码不同的地方是,将counter声明为static,并在两个线程结束后显示最终counter的值。我的理解是,在这里两个instance公用一个声明为static 的 class variable counter,如果在run中对counter进行同步,应该的出像问题一中给出的那样的结果。但结果显示,根本没有同步,交替执行。如果以每个java语句为最小执行粒度考虑,counter最终结果无论同步与否,都应是20,而实际上15,16,17等都有可能,原因是不是因为:实际最小执行粒度为微指令,可能 - thread0 刚取出counter当前值14,还未进行加操作就转向thread1,thread1也取出14,加1,并将结果15放入counter寄存器。然后转向thread0,thread0在刚才取出14上加1,得15,并将counter的值再次更新为15,导致两次加1操作实际上只加了一个1,所以最终结果可能小于20.请指教。

问题三:
class ThreadTest extends Thread {
	static Integer counter = 0;

	public void run() {
		synchronized (ThreadTest.class) {
			for (int i = 0; i < 10; i++) {
				++counter;
				System.out.println(Thread.currentThread().getName() + " "
						+ counter);
				try {
					// System.out.println(Thread.currentThread().getName() +
					// " sleep");
					Thread.sleep(1000);
				} catch (Exception e) {

				}
			}
		}
	}

	public static void main(String args[]) {
		Thread t1 = new ThreadTest();
		Thread t2 = new ThreadTest();
		t1.start();
		t2.start();
		try {
			t1.join();
			t2.join();
		} catch (Exception e) {

		}

		System.out.println(ThreadTest.counter);
	}
}

结果(运行多次,结果一样
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-1 11
Thread-1 12
Thread-1 13
Thread-1 14
Thread-1 15
Thread-1 16
Thread-1 17
Thread-1 18
Thread-1 19
Thread-1 20
20
我的理解:
问题三代码与问题二代码唯一不同之处是将synchronized (counter)改为synchronized (ThreadTest.class)。我的理解是,此时一个线程将获得class的锁(而不是instance的锁),保证对static 的 class variable进行更新同步,所以结果是同步的。我的理解对吗?平常见到的例子都是在static method中用这个(我的例子中run不是static的),比如:
public static int getCount(){
   synchronized(MyClass.class){
      return count;
   }
}

请指教。

谢谢大家!

Integer counter = 0;

你知道Integer 是什么吗?是不可更改的!!!!!

任何对Integer的更改都会造成生成一个新的Integer

记住一点:不要使用不可更改的对象组为同步对象,却对这个对象进行了更高,包括String.

当然,你设置为 final 是可行的选择

private final Integer counter = 0;
快乐渡过每一天,减肥坚持每一天