6

我在需要同步的接口中有许多默认方法,似乎只有这些this方法可用:

default void addUniqueColumns(List<String> names) {
    synchronized (this) {
        ... do something
    }
}

问题是,我想在私有锁上同步,而不是this为了更好地控制:

default void addUniqueColumns(List<String> names) {
    synchronized (lock) {  // how to get a private lock in a default method??
        ... do something
    }
}

解决方案?聪明的解决方法?或者只是忍受它:)!

4

3 回答 3

2

您可以将锁对象放入包可见类的公共静态字段中,让所有默认方法共享锁。锁在您的库内仍然可见,但由于具有默认访问权限的类在您的库外不可见,因此锁对于您的库界面的用户来说是私有的:

class LockHolder { // Package private class
    public static Object LOCK = new Object();
}

public interface ColumnCollection {
    default void addUniqueColumns(List<String> names) {
        synchronized (LockHolder.LOCK) {
            ... do something
        }
    }
}

就您的库作为一个整体而言,与使用private同步 on 相比,此技巧为您提供了与使用锁对象相同的优势this,因为它可以防止外人编写的恶意代码访问您的锁。当然,您图书馆的任何部分都可以抓住锁。

于 2013-12-01T11:48:50.300 回答
1

您可以在接口中添加一个 getLock() 方法,并让每个实现者返回要锁定的对象。

于 2013-12-01T11:38:52.107 回答
0

对于它(以及一些娱乐价值),让我们看看什么是可行的......

我将锁对象放入包可见类的静态字段中,让我所有的默认方法共享锁。锁提供者按需为实例提供自己的锁。当实例被垃圾回收时,锁将从集合中移除。

锁提供者在第一次从实例请求它时创建一个锁,然后返回相同的锁。它看起来像这样:

final class LockProvider {

    private static final WeakHashMap<Widget,Object> widgetLocks = new WeakHashMap<>();

    static Object obtainLock(Widget w) {
        synchronized (widgetLocks) {            
             return locks.computeIfAbsent(w, x -> new Object());
        }
    }

}

现在默认的接口方法如下所示:

public interface Widget{

    default void addSomething(List<String> names) {
        synchronized (LockProvider.obtainLock(this)) {
            ... do something
        }
    }

}

这样做的一个弱点是WeakHashMap使用Object.hashcode()Object.equals()。另一个是,虽然速度很快,但它并不是超高性能。尽管这种方式看起来很聪明……任何需要在私有锁上同步的方法都可以用另一种方式更好地设计。

[更新]

我最后做的是:

1)创建默认方法:

public interface Widget{

    default void addSomething(List<String> something) {
        ... do something 
    }
}

2) 然后创建常规和线程安全的实现

public class WidgetImpl implements Widget{
    ...
}

// Threadsafe version
public class WidgetThreadsafeImpl implements Widget{

    private final Object lock = new Object(); 

    public void addSomething(List<String> something) {
        synchronized(lock){
            super.addSomething(something);
        }
   }

}

默认方法提供算法,实现可以提供线程安全或非线程安全的实现。

于 2013-12-03T10:29:25.493 回答