java - 破译 OSGi 代码片段中的死锁情况

标签 java multithreading osgi deadlock

下面这段代码是为了演示一段OSGi代码中可能发生的死锁,直接取自免费下载的书籍:osgi in practice (Neil Bartlett) 。这本书总体上很容易理解,而且我发现它非常有用。但是,我不确定我是否遵循第 130 页中确定(并稍微讨论过)的并发问题。代码如下:

package org.osgi.book.reader.dbmailbox;

public class BadLockingMailboxRegistrationService implements MailboxRegistrationService {

    private final Map<String,ServiceRegistration> map = 
            new HashMap<String,ServiceRegistration >();

    private final BundleContext context ;

    public BadLockingMailboxRegistrationService(BundleContext context) { 
        this . context = context ;
    }

    // DO NOT DO THIS!
    public synchronized void registerMailbox ( String name, Mailbox mailbox){

        ServiceRegistration priorReg = map.get(name);

        if(priorReg != null) priorReg . unregister ();

        Properties props = new Properties (); 
        props.put(Mailbox.NAME_PROPERTY , name); 
        ServiceRegistration reg = 
                context . registerService (Mailbox.class.getName(), mailbox , props ); 
        map . put(name , reg );
    } 
}

用于显示死锁如何发生的讨论是:

To translate this unhappy situation to OSGi programming, imagine that a thread has taken a lock on an object F. Then it tries to call our register- Mailbox, which locks object K — but it must wait, perhaps because another thread is already executing registerMailbox. One of the callbacks resulting from the service registration then attempts to lock F . The result: two starving threads and no work done.

我理解讨论的第一部分,即线程可能会在对象 F 上获得锁定,该对象尝试调用 registerMailbox,从而在对象 K 上获得锁定(其中 K 是为此特定服务注册的服务对象,或者我认为是这样!)。现在可以肯定的是,另一个线程已经在执行registerMailbox。这意味着,它还需要锁定 K(因为 OSGi 分发单例服务对象)。现在讨论的回调在哪里可能会尝试锁定 F,从而导致死锁?

最佳答案

作者注意到,context.registerService 在执行期间通知同一线程上的服务注册监听器。如果这些监听器之一依次尝试获取锁 F ,则会导致死锁,因为 F 被同时持有 K 的线程持有。 .

线程2:调用registerMailbox并获取K

线程1:在调用registerMailbox之前获取F,然后调用同步的registerMailbox,从而尝试获取K 但由于它由线程 2 持有而阻塞

线程 2:最终执行 context.registerService,进而调用尝试获取 F 的监听器/回调,并由于它由线程 1 持有而阻塞

由于两个线程以相反的顺序获取了两个锁,并且每个线程都获取了其中一个而不是第二个,因此会发生死锁。这实际上并不是一个特定于 OSGI 的问题,但我想是为了说明服务注册涉及监听器通知,并且应该在谨慎持有锁时调用。

关于java - 破译 OSGi 代码片段中的死锁情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32233212/

相关文章:

java - 拖放 ListView 吃其他行 Android

java - 这个结构线程安全吗?

java - 如何从实现相同接口(interface)的多个 bundle 中使用正确的 bundle ?

java - Bean 不在 JNDI 中

java - 如何有效地从服务中调用 Spring 存储库方法?

java - JUnit 中的参数化测试

java - Eclipse 中的线程自动停止(卡住)

php - 在两个PHP脚本之间传递实时套接字

java - 如何根据其符号名称检索 Bundle?

java - 为 Eclipse 插件导入 org.eclipse.core 包