在Java中,synchronized关键字是用来控制线程同步的,是在多线程的环境下,控制synchronized代码段不被多个线程同时执行。Synchronized既可以对代码块使用,也可以加在整个方法上。

  关键是,不要认为给方法或者代码段加上synchronized万事大吉,看下面一段代码:

class Sync {

 public synchronized void test() {
  System.out.println("test开始..");
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("test结束..");
 }
}

class MyThread extends Thread {

 public void run() {
  Sync sync = new Sync();
  sync.test();
 }
}

public class Main {

 public static void main(String[] args) {
  for (int i = 0; i < 3; i++) {
   Thread thread = new MyThread();
   thread.start();
  }
 }
}

  运行结果:

  test开始..
  test开始..
  test开始..
  test结束..
  test结束..
  test结束..

  可以看出来,上面的程序起了三个线程,同时运行test方法,虽然test方法加上了synchronized,但是还是同时运行起来,貌似synchronized没起作用。

  将test方法改成如下:

 public void test() {
  synchronized(this){
   System.out.println("test开始..");
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("test结束..");
  }
 }

  运行结果:

  test开始..
  test开始..
  test开始..
  test结束..
  test结束..
  test结束..

  一切还是这么平静,没有看到synchronized起到一丝作用。

  实际上,synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),只能防止多个线程同时执行同一个对象的这个代码段。

  为什么会这样呢,回到本文的题目上:Java线程同步:synchronized锁住的是代码还是对象。答案是:synchronized锁住的是括号里的对象,而不是代码。对于非静态的synchronized方法,锁的是对象本身也是this。

  当synchronized锁住一个对象后,别的线程如果也想拿到这个对象的锁,必须等待这个线程执行完成释放锁,才能再次给对象加锁,这样才达到线程同步的目的。