繁体   English   中英

了解同步关键字的工作原理

[英]understanding how synchronized keyword works

在下面的代码中,我期望只有两个线程之一才能进入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
  }
}

同步不锁定方法,而是锁定对象。

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

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

您已将2 objects用于2 threads作为其monitor lock ...。

因此,您的代码运行良好, 每个线程都访问其自己对象的锁以访问 halt()方法。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM