本文介绍了Java 中同步是如何工作的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,这是一个示例:>

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s has bowed to me!%n",
                    this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s has bowed back to me!%n",
                    this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

我不明白的是阻塞是如何发生的..main 函数启动了两个线程,每个线程都开始自己的鞠躬.

What I don't get is how the blockage occurs. The main function initiates two threads that each begin their own bows.

同步"块究竟是什么?为同一个对象运行相同的函数(正如我最初认为的那样)?同一类的所有对象的相同功能?同一个对象的所有同步函数?同一个类的所有对象的所有同步函数?

What exactly does 'synchronized' block? The same function running for the same object (as I originally thought)? The same function for all objects of the same class? All synchronized functions for the same object? All synchronized functions for all objects of the same class?

帮帮我.

推荐答案

在 Java 中,每个 Object 都为线程提供了在其上同步或锁定的能力.当一个方法被同步时,该方法使用它的对象实例作为锁.在您的示例中,方法 bowbowBack 都是 synchronized,并且都在同一类 Friend 中.这意味着任何执行这些方法的线程都会在 Friend 实例上同步作为它的锁.

In Java, each Object provides the ability for a Thread to synchronize, or lock, on it. When a method is synchronized, the method uses its object instance as the lock. In your example, the methods bow and bowBack are both synchronized, and both are in the same class Friend. This means that any Thread executing these methods will synchronize on a Friend instance as its lock.

导致死锁的一系列事件是:

A sequence of events which will cause a deadlock is:

  1. 第一个线程开始调用alphonse.bow(gaston),这是synchronizedalphonse Friend目的.这意味着线程必须从该对象获取锁.
  2. 第二个线程开始调用gaston.bow(alphonse),它在gaston Friend同步目的.这意味着线程必须从该对象获取锁.
  3. 现在开始的第一个线程调用 bowback 并等待 gaston 上的锁被释放.
  4. 现在启动的第二个线程调用 bowback 并等待 alphonse 上的锁被释放.
  1. The first Thread started calls alphonse.bow(gaston), which is synchronized on the alphonse Friend object. This means the Thread must acquire the lock from this object.
  2. The second Thread started calls gaston.bow(alphonse), which is synchronized on the gaston Friend object. This means the Thread must acquire the lock from this object.
  3. The first thread started now calls bowback and waits for the lock on gaston to be released.
  4. The second thread started now calls bowback and waits for the lock on alphonse to be released.

要更详细地显示事件的顺序:

To show the sequence of events in much more detail:

  1. main() 开始在主 Therad(称为线程 #1)中执行,创建两个 Friend 实例.到目前为止,一切都很好.
  2. 主线程使用代码 new Thread(new Runnable() { ... 开始它的第一个新线程(称之为线程 #2).线程 #2 调用 alphonse.bow(gaston),它是 alphonse Friend 对象上的 synchronized.因此,线程 #2 获得了 alphonse 对象的锁"code>alphonse 对象并进入 bow 方法.
  3. 此处出现一个时间片,原始线程有机会进行更多处理.
  4. 主线程启动第二个新线程(称为线程 #3),就像第一个线程一样.线程 #3 调用 gaston.bow(alphonse),它在 gaston Friend 对象上同步.由于还没有人获得 gaston 对象实例的锁",线程 #3 成功地获得了这个锁并进入了 bow 方法.
  5. 此处出现一个时间片,线程 #2 有机会进行更多处理.
  6. 线程 #2 现在调用 bower.bowBack(this);,其中 bower 是对 gaston 实例的引用.这在逻辑上等同于 gaston.bowBack(alphonse) 的调用.因此,此方法在 gaston 实例上同步.此对象的锁已被获取并由另一个线程(线程 #3)持有.因此,线程 #2 必须等待 gaston 上的锁被释放.线程进入等待状态,允许线程 #3 进一步执行.
  7. 线程 #3 现在调用 bowback,在本例中它在逻辑上与调用 alphonse.bowBack(gaston) 相同.为此,它需要获取 alphonse 实例的锁,但该锁由线程 #2 持有.该线程现在处于等待状态.
  1. main() begins to execute in the main Therad (call it Thread #1), creating two Friend instances. So far, so good.
  2. The main Thread starts its first new Thread (call it Thread #2) with the code new Thread(new Runnable() { .... Thread #2 calls alphonse.bow(gaston), which is synchronized on the alphonse Friend object. Thread #2 thus acquires the "lock" for the alphonse object and enters the bow method.
  3. A time slice occurs here and the original Thread gets a chance to do more processing.
  4. The main Thread starts a second new Thread (call it Thread #3), just like the first one. Thread #3 calls gaston.bow(alphonse), which is synchronized on the gaston Friend object. Since no-one has yet acquired the "lock" for the gaston object instance, Thread #3 successfully acquires this lock and enters the bow method.
  5. A time slice occurs here and Thread #2 gets a chance to do more processing.
  6. Thread #2 now calls bower.bowBack(this); with bower being a reference to the instance for gaston. This is the logical equivalent of a call of gaston.bowBack(alphonse). Thus, this method is synchronized on the gaston instance. The lock for this object has already been acquired and is held by another Thread (Thread #3). Thus, Thread #2 has to wait for the lock on gaston to be released. The Thread is put into a waiting state, allowing Thread #3 to execute further.
  7. Thread #3 now calls bowback, which in this instance is logically the same as the call alphonse.bowBack(gaston). To do this, it needs to acquire the lock for the alphonse instance, but this lock is held by Thread #2. This Thread is now put into a waiting state.

而您现在处于两个线程都无法执行的位置.线程#2 和线程#3 都在等待释放锁.但是如果没有线程取得进展,这两个锁都不能被释放.但是如果不释放锁,两个线程都无法取得进展.

And you are now in a position where neither Thread can execute. Both Thread #2 and Thread #3 are waiting for a lock to be released. But neither lock can be released without a Thread making progress. But neither thread can make progress without a lock being released.

因此:死锁!

死锁通常取决于发生的特定事件序列,这会使调试变得困难,因为它们很难重现.

Deadlocks very often depend on a specific sequence of events occurring, which can make then difficult to debug since they can be difficult to reproduce.

这篇关于Java 中同步是如何工作的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 00:35