当前位置: 首页 > 面试题库 >

两个线程可以同时访问同步方法吗?

袁亦
2023-03-14
问题内容

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();
    }
}

当我运行该程序时,我得到的输出为

阿方斯:加斯顿向我鞠躬!加斯顿:阿方斯向我鞠躬!

那么,两个线程可以同时访问同步方法吗?


问题答案:

两个线程可以同时访问同步方法吗?

这取决于两个线程试图锁定的对象实例。两个线程不能synchronized在同一对象实例上访问相同的方法。一个将获得锁,另一个将阻塞,直到第一个线程离开该方法。

在您的示例中,实例方法在包含它们的对象上同步。在这种情况下,调用alphonse.bow(...)时将锁定该alphonse对象。gaston.bow(...)gaston

您可以通过两种方法来获取一个对象的多个实例以锁定同一对象。

  • 您可以将方法设为staticsynchronized在这种情况下,它们将锁定类对象本身。每个类加载器仅这些对象之一。

    public static synchronized void bow(Friend bower) {
    
  • 它们都可以锁定已定义的静态对象。就像是:

        private static final Object lockObject = new Object();
    ...
    public void bow(Friend bower) {
        synchronized (lockObject) {
            ....
        }
    }
  • 或者,如果您不想将其设为静态,则可以传入该对象以进行锁定。

您的输出可能类似于以下内容:

  1. gaston线程(可能)开始第一和电话bow(alphonse)
  2. 这将锁定gaston对象并输出:Gaston: Alphonse has bowed to me!
  3. 它呼吁alphonse.bowBack(this)
  4. 该调用将锁定alphonse对象并输出:Alphonse: Gaston has bowed back to me!
  5. alphonse.bowBack(this)退出,解锁alphonse对象。
  6. gaston.bow(alphonse)退出,解锁gaston对象。
  7. 然后gaston线程退出。
  8. alphonse线程(可能)明年开始,并呼吁bow(gaston)
  9. 这将锁定alphonse对象并输出:Alphonse: Gaston has bowed to me!
  10. 它呼吁gaston.bowBack(this)
  11. 该调用将锁定gaston对象并输出:Gaston: Alphonse has bowed back to me!
  12. gaston.bowBack(this)退出,解锁gaston对象。
  13. alphonse.bow(gaston)退出,解锁alphonse对象。

这可能以许多不同的顺序发生。alphonse即使start()稍后会调用该方法,该线程也可以首先运行。锁唯一使您无法alphonse.bow(...)使用的alphonse.bowBack(...)是当前正在运行的if
的调用。正如@ user988052指出的那样,由于每个线程都锁定自己的对象,然后尝试锁定另一个对象,因此很容易会出现死锁。



 类似资料:
  • 问题内容: 我有4种方法(,,和一类)。方法,并有方法。另外,我有4个线程,,和分别。 如果访问方法(同步方法),线程访问方法(同步方法)是否可以同时进行?如果不是,则t2的状态如何? 问题答案: 如果t1访问m1方法(同步方法),t2线程可以同时访问m2方法(同步方法)吗? 该关键字适用于 目标水平 ,且只有一个线程可持有对象的锁。因此,只要您在谈论同一个对象,那么 否 ,它将等待释放进入时获得

  • 我正在尝试为我的大学网络做一个聊天应用程序。它实际上是两个程序:一个用于服务器,另一个用于客户端。所有客户端消息都将发送到服务器,发送方的名称和预期目标将预先添加到服务器。服务器使用此信息将消息发送给目标。 我写了一个程序,模拟了服务器端的东西,有4个类:模型、消息中心、接收者和发送者。 接收器在独立线程上生成字符串,并通过随机超时将其添加到MessageCentre中的队列中。发件人检查队列是否

  • 本文向大家介绍C# 线程同步的方法,包括了C# 线程同步的方法的使用技巧和注意事项,需要的朋友参考一下 一、进程内部的线程同步 1、使用lock,用法如下: 特性:只能传递对象,无法设置等待超时 2、使用:InterLocked(原子操作) 其在System.Threading命名空间下,Interlocked实际是类控制计数器,从而实现进程的同步,其很容易实现生产者消费者模型 3、使用Monit

  • 问题内容: 我正在尝试同步三个线程以打印012012012012…。但是它不能正常工作。每个线程都分配有一个编号,当它从主线程接收到信号时将打印该编号。以下程序有问题,我无法捕获。 问题答案: 您需要更多的协调。该notify调用不会立即唤醒线程并强制其继续执行。相反,您可以考虑notify将电子邮件发送给线程以使其可以继续进行。想象一下,如果您想让3个朋友按顺序给您打电话。您向朋友1发送了一封电

  • 问题内容: 我在同一文件中有以下程序。我已经同步了run()方法。 输出是 我的问题是,为什么同步方法同时允许“我的线程1”和“我的线程4”线程访问? 问题答案: 方法在实例级别工作。 类的每个实例都有自己的锁。每次输入实例的任何方法都将获取该锁。这样可以防止多个线程 在同一个实例上 调用方法(请注意,这还可以防止在同一个实例上调用 不同的 方法)。 现在,由于您有两个类实例,因此每个实例都有自己