Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程-死锁的解决方案?_Java_Multithreading_Thread Safety_Deadlock - Fatal编程技术网

Java线程-死锁的解决方案?

Java线程-死锁的解决方案?,java,multithreading,thread-safety,deadlock,Java,Multithreading,Thread Safety,Deadlock,我已经编写了一些Java代码来演示线程中的死锁。就其本身而言,我通常会得到两行输出和一个异常,有时在预期的输出行之前,有时在输出行之后。我得到的异常是transfer()方法第一行的NullPointerException 我遇到的问题是我想知道如何解决这个死锁问题。我在StackOverflow上搜索了此问题,并找到了此页面: 作为解决方案,我尝试了Will Hartung和Dreamcash发布的内容,但在尝试使用synchronize或ReentrantLock对象时仍然会出现异常 代码

我已经编写了一些Java代码来演示线程中的死锁。就其本身而言,我通常会得到两行输出和一个异常,有时在预期的输出行之前,有时在输出行之后。我得到的异常是transfer()方法第一行的NullPointerException

我遇到的问题是我想知道如何解决这个死锁问题。我在StackOverflow上搜索了此问题,并找到了此页面:

作为解决方案,我尝试了Will Hartung和Dreamcash发布的内容,但在尝试使用synchronize或ReentrantLock对象时仍然会出现异常

代码如下:

科目类别:

public class Account {

    int id;
    double balance;

    public Account(int id, double balance){
        this.id = id;
        this.balance = balance;
    }

    public void withdraw(double amount){
        balance = balance - amount;
    }

    public void deposit(double amount){
        balance = balance + amount;
    }

    public int getID(){
        return id;
    }

    public double getBalance(){
        return balance;
    }

}
public class Bank{

    static Bank bank;

    Account a1;
    Account a2;

    private Bank(){}

    public static Bank getInstance(){
        if(bank==null){
            bank = new Bank();
            bank.setAccountOne(new Account(1, 100));
            bank.setAccountTwo(new Account(2, 100));
        }

        return bank;
    }


    public void transfer(Account from, Account to, double amount){
        from.withdraw(amount);
        to.deposit(amount);
    }


    public Account getAccountOne(){
        return a1;
    }

    public Account getAccountTwo(){
        return a2;
    }
    public void setAccountOne(Account acc){
        a1 = acc;
    }
    public void setAccountTwo(Account acc){
        a2 = acc;
    }

}
public class PersonOne implements Runnable {

    public void run() {

        Bank bank = Bank.getInstance();     

        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a2, a1, 10);      

        System.out.println("T1: New balance of A1 is " + a1.getBalance());
        System.out.println("T1: New balance of A2 is " + a2.getBalance());
    }

}
public class PersonTwo implements Runnable {

    public void run() {
        Bank bank = Bank.getInstance();
        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a1, a2, 10);

        System.out.println("T2: New balance of A1 is " + a1.getBalance());
        System.out.println("T2: New balance of A2 is " + a2.getBalance());
    }

}
银行类(单身人士):

public class Account {

    int id;
    double balance;

    public Account(int id, double balance){
        this.id = id;
        this.balance = balance;
    }

    public void withdraw(double amount){
        balance = balance - amount;
    }

    public void deposit(double amount){
        balance = balance + amount;
    }

    public int getID(){
        return id;
    }

    public double getBalance(){
        return balance;
    }

}
public class Bank{

    static Bank bank;

    Account a1;
    Account a2;

    private Bank(){}

    public static Bank getInstance(){
        if(bank==null){
            bank = new Bank();
            bank.setAccountOne(new Account(1, 100));
            bank.setAccountTwo(new Account(2, 100));
        }

        return bank;
    }


    public void transfer(Account from, Account to, double amount){
        from.withdraw(amount);
        to.deposit(amount);
    }


    public Account getAccountOne(){
        return a1;
    }

    public Account getAccountTwo(){
        return a2;
    }
    public void setAccountOne(Account acc){
        a1 = acc;
    }
    public void setAccountTwo(Account acc){
        a2 = acc;
    }

}
public class PersonOne implements Runnable {

    public void run() {

        Bank bank = Bank.getInstance();     

        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a2, a1, 10);      

        System.out.println("T1: New balance of A1 is " + a1.getBalance());
        System.out.println("T1: New balance of A2 is " + a2.getBalance());
    }

}
public class PersonTwo implements Runnable {

    public void run() {
        Bank bank = Bank.getInstance();
        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a1, a2, 10);

        System.out.println("T2: New balance of A1 is " + a1.getBalance());
        System.out.println("T2: New balance of A2 is " + a2.getBalance());
    }

}
个人类别:

public class Account {

    int id;
    double balance;

    public Account(int id, double balance){
        this.id = id;
        this.balance = balance;
    }

    public void withdraw(double amount){
        balance = balance - amount;
    }

    public void deposit(double amount){
        balance = balance + amount;
    }

    public int getID(){
        return id;
    }

    public double getBalance(){
        return balance;
    }

}
public class Bank{

    static Bank bank;

    Account a1;
    Account a2;

    private Bank(){}

    public static Bank getInstance(){
        if(bank==null){
            bank = new Bank();
            bank.setAccountOne(new Account(1, 100));
            bank.setAccountTwo(new Account(2, 100));
        }

        return bank;
    }


    public void transfer(Account from, Account to, double amount){
        from.withdraw(amount);
        to.deposit(amount);
    }


    public Account getAccountOne(){
        return a1;
    }

    public Account getAccountTwo(){
        return a2;
    }
    public void setAccountOne(Account acc){
        a1 = acc;
    }
    public void setAccountTwo(Account acc){
        a2 = acc;
    }

}
public class PersonOne implements Runnable {

    public void run() {

        Bank bank = Bank.getInstance();     

        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a2, a1, 10);      

        System.out.println("T1: New balance of A1 is " + a1.getBalance());
        System.out.println("T1: New balance of A2 is " + a2.getBalance());
    }

}
public class PersonTwo implements Runnable {

    public void run() {
        Bank bank = Bank.getInstance();
        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a1, a2, 10);

        System.out.println("T2: New balance of A1 is " + a1.getBalance());
        System.out.println("T2: New balance of A2 is " + a2.getBalance());
    }

}
人两类:

public class Account {

    int id;
    double balance;

    public Account(int id, double balance){
        this.id = id;
        this.balance = balance;
    }

    public void withdraw(double amount){
        balance = balance - amount;
    }

    public void deposit(double amount){
        balance = balance + amount;
    }

    public int getID(){
        return id;
    }

    public double getBalance(){
        return balance;
    }

}
public class Bank{

    static Bank bank;

    Account a1;
    Account a2;

    private Bank(){}

    public static Bank getInstance(){
        if(bank==null){
            bank = new Bank();
            bank.setAccountOne(new Account(1, 100));
            bank.setAccountTwo(new Account(2, 100));
        }

        return bank;
    }


    public void transfer(Account from, Account to, double amount){
        from.withdraw(amount);
        to.deposit(amount);
    }


    public Account getAccountOne(){
        return a1;
    }

    public Account getAccountTwo(){
        return a2;
    }
    public void setAccountOne(Account acc){
        a1 = acc;
    }
    public void setAccountTwo(Account acc){
        a2 = acc;
    }

}
public class PersonOne implements Runnable {

    public void run() {

        Bank bank = Bank.getInstance();     

        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a2, a1, 10);      

        System.out.println("T1: New balance of A1 is " + a1.getBalance());
        System.out.println("T1: New balance of A2 is " + a2.getBalance());
    }

}
public class PersonTwo implements Runnable {

    public void run() {
        Bank bank = Bank.getInstance();
        Account a1 = bank.getAccountOne();
        Account a2 = bank.getAccountTwo();

        bank.transfer(a1, a2, 10);

        System.out.println("T2: New balance of A1 is " + a1.getBalance());
        System.out.println("T2: New balance of A2 is " + a2.getBalance());
    }

}
最后是我的主要方法

    public static void main(String[] args){
        PersonOne p1 = new PersonOne();
        PersonTwo p2 = new PersonTwo();

        Thread t1 = new Thread(p1);
        Thread t2 = new Thread(p2);

        t1.start();
        t2.start();
    }
我得到的异常是transfer()方法第一行的NullPointerException

我遇到的问题是我想知道如何解决这个死锁问题

您的代码不可能引发任何死锁。它引发的是写可见性问题:其中一个线程调用lazy
Bank
初始值设定项,而另一个线程没有看到写操作

要获得死锁,首先需要任何类型的锁定(synchronized关键字
synchronized
)。通过将
synchronized
添加到
getInstance
方法,您的特定NPE问题将得到解决,并且不会引入任何死锁

我的结论是,您最好阅读一些关于Java并发性的介绍性材料

我得到的异常是transfer()方法第一行的NullPointerException

我遇到的问题是我想知道如何解决这个死锁问题

您的代码不可能引发任何死锁。它引发的是写可见性问题:其中一个线程调用lazy
Bank
初始值设定项,而另一个线程没有看到写操作

要获得死锁,首先需要任何类型的锁定(synchronized关键字
synchronized
)。通过将
synchronized
添加到
getInstance
方法,您的特定NPE问题将得到解决,并且不会引入任何死锁


我的结论是,您最好阅读一些关于Java并发性的介绍性材料。

有许多解决方案,其中一些不太明显的是

  • 使用一个线程,不要使用锁。在本例中,由于锁的开销超过了正在完成的工作,因此只需一个线程,代码将变得更简单、更快
  • 因为这只是一个示例,所以只需使用一个全局锁。这不会像多个锁那样执行,但它要简单得多,如果您不需要性能,那么应该做得更简单,更不容易出现错误。这不会导致死锁
  • 如果因为这是作业而必须使用多锁,则可以确保始终以相同的顺序锁定。您可以通过按唯一键对对象进行排序并始终首先锁定“第一个”项来完成此操作
  • 最后,您可以在第二个帐户上使用tryLock以任何顺序锁定对象。如果失败,请释放两个锁并重试。您可以使用不安全的.tryMonitor()在监视器上执行tryLock

有许多解决方案,其中一些不太明显的是

  • 使用一个线程,不要使用锁。在本例中,由于锁的开销超过了正在完成的工作,因此只需一个线程,代码将变得更简单、更快
  • 因为这只是一个示例,所以只需使用一个全局锁。这不会像多个锁那样执行,但它要简单得多,如果您不需要性能,那么应该做得更简单,更不容易出现错误。这不会导致死锁
  • 如果因为这是作业而必须使用多锁,则可以确保始终以相同的顺序锁定。您可以通过按唯一键对对象进行排序并始终首先锁定“第一个”项来完成此操作
  • 最后,您可以在第二个帐户上使用tryLock以任何顺序锁定对象。如果失败,请释放两个锁并重试。您可以使用不安全的.tryMonitor()在监视器上执行tryLock

    • 谢谢您的回答

      我目前正在学习线程技术。在上面,我故意尝试创建一个死锁,这样我就可以学习如何解决死锁问题(如果我真的想要一个实现上述功能的程序,我只需要避免多线程)

      我使用单例的原因是两个线程将尝试使用相同的对象


      所以。。。上面是我用来尝试重新创建死锁的代码,所以我希望在运行时出现问题/异常。我试图修复它的一种方法是重写transfer方法,使其如下所示:

      public void transfer(Account from, Account to, double amount){      
          synchronized(from){
              synchronized(to){
                  from.withdraw(amount);
                  to.withdraw(amount);
              }
          }
      }
      
      但是我会在synchronized(from)行上得到一个NullPointerException

      我也在transfer方法中尝试了这一点(account中有一个ReentrantLock对象)。但是这次我在读取.getLock().unlock()的行中得到一个NullPointerException


      谢谢你的回答

      我目前正在学习线程技术。在上面,我故意尝试创建一个死锁,这样我就可以学习如何解决死锁问题(如果我真的想要一个实现上述功能的程序,我只需要避免多线程)

      我使用单例的原因是两个线程将尝试使用相同的对象


      所以。。。上面是我用来尝试重新创建死锁的代码,所以我希望在运行时出现问题/异常。我试图修复它的一种方法是重写transfer方法,使其如下所示:

      public void transfer(Account from, Account to, double amount){      
          synchronized(from){
              synchronized(to){
                  from.withdraw(amount);
                  to.withdraw(amount);
              }
          }
      }
      
      但是我会在synchronized(from)行上得到一个NullPointerException

      我也