1

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

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
  }
}
4

5 回答 5

7

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

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

于 2012-09-13T17:30:42.590 回答
2

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

于 2012-09-13T17:31:37.080 回答
1

你已经用作2 objects他们2 threadsmonitor lock......

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

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

于 2012-09-13T17:32:01.570 回答
1

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

于 2012-09-13T17:33:19.577 回答
1

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

于 2012-09-13T17:36:14.410 回答