了解synchronized关键字的工作原理

时间:2012-09-13 17:28:04

标签: java synchronized

在下面的代码中,我只希望两个线程中的一个进入halt()函数,然后暂停程序。但似乎两个线程都进入synchronized halt()函数。为什么会发生这种情况?

package practice;

class NewThread implements Runnable {
  String name; // name of thread
  Thread t;
  boolean suspendFlag;

  NewThread(String threadname) {
    name = threadname;
    t = new Thread(this, name);
    System.out.println("New thread: " + t);
    suspendFlag = false;
    t.start(); // Start the thread
  }

  // This is the entry point for thread.
  public void run() {
    try {
      for(int i = 15; i > 0; i--) {
        System.out.println(name + ": " + i);
        Thread.sleep(200);
        Runtime r = Runtime.getRuntime();
        halt();
      }
    } catch (InterruptedException e) {
      System.out.println(name + " interrupted.");
    }
    System.out.println(name + " exiting.");
  }

  synchronized void halt() throws InterruptedException
  {
      System.out.println(name + " entered synchronized halt");
      Runtime r = Runtime.getRuntime();
      Thread.sleep(1000);
      r.halt(9);
      System.out.println(name + " exiting synchronized halt"); // This should never execute
  }
}

class Practice{
  public static void main(String args[]) {
    NewThread ob1 = new NewThread("One");
    NewThread ob2 = new NewThread("Two");

    // wait for threads to finish
    try {
      System.out.println("Waiting for threads to finish.");
      ob1.t.join();
      ob2.t.join();
    } catch (InterruptedException e) {
      System.out.println("Main thread Interrupted");
    }

    System.out.println("Main thread exiting."); // This should never execute
  }
}

5 个答案:

答案 0 :(得分:7)

synchronized不会锁定方法,它会锁定一个对象。

你有一个方法,但有两个对象。每个线程锁定自己的对象并调用halt()。

答案 1 :(得分:2)

在每个对象上完成同步。如果您有2个对象,则2个线程可能同时进入halt()方法。您可以使方法静态以实现您想要的效果。通过使其成为静态,锁将被放置在相应的Class对象(NewThreadOne.class)上,该对象在NewThreadOne的实例数量方面是唯一的。

答案 2 :(得分:1)

您已使用2 objects 2 threads作为monitor lock ....

所以你的代码运行正常,每个线程访问自己对象的锁来访问 halt()方法....

synchonized keyword中,实现对象的锁定,线程可以通过该锁定访问该类中的synchronized methods or atomic statements ......

答案 3 :(得分:1)

synchronized方法正在使用此方法进行锁定。在您的情况下,您有2个不同的对象,因为您正在构建2个线程实例,因此您不会锁定同一个对象。为了获得您期望的同步行为,您需要制作halt方法static

答案 4 :(得分:1)

不建议在java synchronized块中使用String对象作为锁,因为string是不可变对象,文字字符串和实习字符串存储在String池中。所以,如果代码的任何其他部分或任何第三方库使用相同的字符串,那么它们将被锁定在同一个对象上,尽管它们完全不相关,这可能导致意外的行为和糟糕的性能。而不是String对象,建议在同步块上使用新的Object()进行Java同步。