java - 如何用不同的方法锁定不同的对象?

标签 java multithreading

我有 2 个线程,我想用这些线程运行 Student 对象的不同方法。问题是当我运行此代码时,t2 线程等待 t1 完成同步块(synchronized block)。

为什么要等待 t1 完成?如何用不同的方法锁定不同的对象而不互相阻塞?

这是主要方法;

Student student = new Student();
Thread t1 = new Thread(() -> {
    try {
        student.addA();
    } catch (InterruptedException ex) {
        Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
    }
});

Thread t2 = new Thread(() -> {
    try {
        student.addB();
    } catch (InterruptedException ex) {
        Logger.getLogger(JavaApplication1.class.getName()).log(Level.SEVERE, null, ex);
    }
});

t1.start();
t2.start();

这是学生类(class);

public class Student {

  private Integer a = 0;
  private Integer b = 0;

  public void addA() throws InterruptedException{
      System.out.println("addA start");
      synchronized(a){
          System.out.println("addA sync start");
          a++;
          Thread.sleep(5000);
      }
      System.out.println("addA end");
  }

  public void addB() throws InterruptedException{
      System.out.println("addB start");
      synchronized(b){
          System.out.println("addB sync start");
          b++;
          Thread.sleep(5000);
      }
      System.out.println("addB end");
  }

}

最佳答案

这个:

private Integer a = 0;
private Integer b = 0;

实际上与此相同:

private Integer a = Integer.valueOf(0);
private Integer b = Integer.valueOf(0);

the result of Integer.valueOf(0) is cached ,因此您实际上是在同一个对象上同步。

您可以使用new Integer(0)来获取不同的Integer实例。

但这只是在一次迭代中解决问题:

a++;

实际上是:

a = Integer.valueOf(a.intValue() + 1);

因此您可能会再次遇到相同的问题,至少在 a 的值超出 Integer.valueOf 方法缓存的值范围之前(至少127,但取决于实现)。

您可以应用相同的技巧:

a = new Integer(a.intValue() + 1);

但是,在可变引用上进行同步是一个非常糟糕的主意,因为一旦执行了该行,另一个线程就可以进入该同步块(synchronized block)。 (不是那些已经被阻止进入的线程,而是任何随后到达同步的线程)。

相反,您应该为每个 ab 创建一个单独的锁定对象:

private final Object aLock = new Object();
private final Object bLock = new Object();

并同步这些,而不是相应的ab

关于java - 如何用不同的方法锁定不同的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46911543/

相关文章:

ios - 如果使用 [NSOperation start] 手动执行,NSOperation 将在哪个线程上运行?

python - 套接字P2P和线程

multithreading - 在 Groovy 中加入线程

Java ArrayList 线程不安全示例说明

java - 如何在 JPanel 上用 Java 绘制 "Class"

java - setPixel 的颜色

java - Eclipse HelloWorldSWT 教程 : cannot access import packages

python - 如何限制Python 3中多线程程序中的API调用?

java - 使用JDBC实现用户名密码认证

java - 将字符串转换为类型 'Date'