当两个锁定的线程(通过一个变量)切换它们的一个变量并尝试访问另一个时会发生什么?

What happens when two locked threads (by a variable), switch one of their variable and try to access another?

(我刚开始线程,所以我错的可能性很大)

如果相同class的两个线程,它们的一个变量进入同步方法,并且它们切换它们的一个变量,并尝试使用切换的变量访问另一个同步方法。会出现死锁吗?为什么?

我所说的一个例子: class:

public class Person extends Thread{
    public Hand leftHand;
    public Hand rightHand;
    public String name;
    public Person friend;

    public Person(Hand a, Hand b, String name, Person f){
        this.leftHand = a;
        this.rightHand = b;
        this.name = name;
        this.friend = f;
    }

    public void switchHands(){
        if(leftHand.color.equals(rightHand.color)){
            Hand temp = this.rightHand;
            this.rightHand = friend.rightHand;
            friend.rightHand = temp;
        }
    }

    public void run(){
        synchronized (leftHand){
            System.out.println(this.name + " locked with " + this.leftHand);
            switchHands();
            synchronized (rightHand){
                 System.out.println(this.name + " locked with " + this.rightHand);   
            }
        }
    }

    public static class Hand{
        String color;
        public Hand(String c){ this.color = c; }  
    }
}

主要是:

public static void main(String[] args){
    Hand whiteHand = new Hand("white");
    Hand blackHand = new Hand("black");
    Person one = new Person(whiteHand, whiteHand, "one", null);
    Person second = new Person(blackHand, blackHand, "second", null);
    one.friend = second;
    second.friend = one;
    one.start();
    second.start()
}

如您所见,两个线程(一个和两个)被锁定在 synchronized (leftHand) 中,之后其中一个线程至少切换手(右手),然后 - 我们尝试访问synchronized (rightHand),可能发生了死锁。

我能理解逻辑,但是当我换手时,直觉上我认为我会复制另一只手的内容,但是我不明白为什么会出现死锁

P.S我觉得我的标题不够准确,欢迎修改。

不要将您的代码视为在 leftHandrightHand 上同步,因为那不是它正在做的事情。您实际上是在 whiteHandblackHand 上同步。您的两个不同的 Person 对象,当 运行、 可能 看起来像这样:

Person one: synchronized whiteHand
Person two: synchronized blackHand
Person two: synchronized whiteHand
Person one: synchronized blackHand

你能看出这怎么行不通吗?您没有阻止其他线程在内部同步块上进行同步。第二个人有可能获得 blackHand 锁,然后等待第一个人释放 whiteHand 锁。但是,第一个人不会释放已经持有的 whiteHand 锁,因为它正在等待第二个人释放 blackHand 锁,而后者又在等待第一个人,依此类推。这种循环依赖会导致死锁。

此处的快速修复是简单地为每个 Person 实例使用一个锁,并通过将 color 设置为 final 使 Hand 线程安全。

之后,您需要将 name 设置为最终并同步对 friend 的访问,以使 Person 线程安全。