正在打破对象死锁



晚上好!亲爱的,我提前为糟糕的短信道歉。英语不是我的母语。问题是:有代码,我甚至弄清楚了死锁是如何实现的。但如何摆脱困境是个问题。我被告知要么同步捕获,要么顺序调用线程。

我尝试了如下:

  • 我从方法中删除监视器,并在类中创建一个静态对象并将其放入监视器中,如果您调用线程,它会工作,但如果您将线程调用到循环中,一切都会崩溃
  • 我还试图将函数so bower.bowBack(this(重写为this.bowBack(bower(,这样就不会从1个线程调用2个对象,但仍然值得将其放入循环中,而且我们没有所需的东西

请告诉我你如何解决这个问题?

更新:我很抱歉没有提供信息。我会进步的。根据分配,您需要输出2个流:

  • A:G开枪打了我
  • A: 我回击
  • G: 他开枪打了我

(流1(

G:他开枪打了我
  • G: 我回击
  • A: G开枪打了我
  • (流2(

    他就是这么做的。但一旦你把它放进循环中,它就会冻结。如何组织线程的顺序工作?我不知道如何正确地实现它。

    package pr1;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    //package ru.philosophyit;
    
    public class DeadLock {
    static class Friend {
    private final String name;
    
    private final Lock lock = new ReentrantLock();
    
    public Friend(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    
    public void bow(Friend bower) {
    
    boolean Lock_my = false;
    boolean Lock_bower = false;
    
    try
    {
    
    while(!Lock_my || !Lock_bower)
    {
    Lock_my = this.lock.tryLock(100, TimeUnit.MILLISECONDS);
    Lock_bower = bower.lock.tryLock(100, TimeUnit.MILLISECONDS);
    }
    
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    System.out.format("%s: стреляю в ответ!n", this.name);
    
    bower.bowBack(this);
    
    this.lock.unlock();
    bower.lock.unlock();
    }
    catch(InterruptedException e)
    {
    e.printStackTrace();
    }
    }
    
    public void bowBack(Friend bower) {
    
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    }
    }
    
    /**
    * Точка входа в программу
    
    *
    * @param args аргументы командной строки
    */
    
    public static void main(String[] args) {
    Friend alphonse = new Friend("Alphonse");
    Friend gaston = new Friend("Gaston");
    
    for (int i = 0; i < 5; i++)
    {
    new Thread(() -> alphonse.bow(gaston)).start();
    
    new Thread(() -> gaston.bow(alphonse)).start();
    }
    }
    
    }
    

    我还对一个静态对象进行了同步,循环正常工作,但输出不是顺序的。即可以存在1个流1个流2个流2流1个,而不是1个流。我不明白为什么。

    package pr1;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    //package ru.philosophyit;
    
    public class DeadLock {
    static Object o = new Object();
    
    static class Friend {
    private final String name;
    
    
    public Friend(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    
    public void bow(Friend bower) {
    
    //synchronized(getClass())
    synchronized(o)
    {   
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    System.out.format("%s: стреляю в ответ!n", this.name);
    
    bower.bowBack(this);
    }
    }
    
    public void bowBack(Friend bower) 
    {
    //synchronized(getClass())
    synchronized(o)
    {
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    }
    }
    }
    
    
    public static void main(String[] args) {
    Friend alphonse = new Friend("Alphonse");
    Friend gaston = new Friend("Gaston");
    
    // for (int i = 0; i < 10; i++)
    {
    new Thread(() -> alphonse.bow(gaston)).start();
    
    new Thread(() -> gaston.bow(alphonse)).start();
    }
    }
    
    }
    

    结果是2,代码非常合适,线程的工作顺序并不重要,但消息的顺序很重要。但是,当线程增加时,我们需要大量的同步对象,这使方法2变得复杂。他们说你只需要换几行字,一切都会好起来的。3代码是任务本身的原始形式的代码(因此需要更改行的地方(。我知道2个线程处理不同的对象,因此同步无法正常工作(我们在bowBack上进行阻塞,也许值得重写它?(

    package pr1;
    import java.util.concurrent.SynchronousQueue;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    //package ru.philosophyit;
    public class DeadLock {
    static Object o = new Object();
    
    static class Friend {
    private final String name;
    
    
    public Friend(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    
    public synchronized void bow(Friend bower) {
    
    {   
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    System.out.format("%s: стреляю в ответ!n", this.name);
    
    bower.bowBack(this);
    }
    }
    
    public synchronized void bowBack(Friend bower) 
    {
    {
    System.out.format("%s: %s подстрелил меня!n", this.name, bower.getName());
    }
    }
    }
    
    
    public static void main(String[] args) {
    Friend alphonse = new Friend("Alphonse");
    Friend gaston = new Friend("Gaston");
    
    for (int i = 0; i < 10; i++)
    {
    new Thread(() -> alphonse.bow(gaston)).start();
    
    new Thread(() -> gaston.bow(alphonse)).start();
    
    
    }
    }
    
    }
    

    我们能把箭头看作一种资源吗?

    import java.util.concurrent.*;
    
    public class Bowmen implements Runnable{
    String name;
    Bowmen target;
    SynchronousQueue<Object> queue = new SynchronousQueue<>();
    public Bowmen(String name){
    this.name = name;
    }
    
    public void shoot(String name, Object o) throws InterruptedException{
    System.out.println(this.name + " : " + name + " shot me.");
    queue.put(o);
    }
    
    public void run(){
    try{
    Object o = queue.take();
    System.out.println(this.name + " : I will shoot " + target.name);
    target.shoot(name, o);
    } catch(InterruptedException e){
    //just finish.
    }
    }
    public void setTarget(Bowmen t){
    target = t;
    }
    
    public static void main(String[] args) throws Exception{
    
    Bowmen a = new Bowmen("a");
    Bowmen b = new Bowmen("b");
    
    a.setTarget(b);
    b.setTarget(a);
    
    for(int i = 0; i<5; i++){
    new Thread(a).start();
    new Thread(b).start();
    }
    //all the threads are waiting because there is no resource to share yet.
    a.shoot( null, new Object() );
    }
    }
    

    这将产生输出

    a:零射我。
    a:我会射b
    b:一射我。
    b:我会射a
    。。。

    它将以";a:b开枪打了我;但是程序不会完成,因为没有线程从队列中取出,让最后一次调用shoot完成。

    最新更新