Java: Synchronization Utility

2020-06-24 02:12发布

问题:

I am asking this purely to determine the worthwhile-ness of implementing the class in Question ...

Do you know of a Java utility class that takes an un-synchronized instance, uses reflection to investigate that instance, and returns the input instance "wrapped" within synchronized calls ?

( ie: A factory which creates a synchronized delegate class for any instance )

回答1:

I like Jon Skeet's answer; it's seeing the forest instead of the trees. But to answer the question:

Assuming that the instance belongs to some interface, it's easy to use java.lang.reflect.Proxy to do this.

public final class SynchronizedFactory {
    private SynchronizedFactory() {}

    public static <T> T makeSynchronized(Class<T> ifCls, T object) {
        return ifCls.cast(Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                new Class<?>[] {ifCls},
                new Handler<T>(object)));
    }

    private static class Handler<T> implements InvocationHandler {
        private final T object;

        Handler(T object) {
            this.object = object;
        }

        @Override
        public Object invoke(Object proxy, Method method,
                Object[] args) throws Throwable {
            synchronized (object) {
                return method.invoke(object, args);
            }
        }
    }
}

This code is not tested, by the way. Use at your own risk.



回答2:

No, I don't know of anything which does that - and I'd rarely want to use it.

Synchronizing individual operations is rarely a useful feature. Typically you want to synchronize a few operations at a time. Something which simply synchronizes individual operations gives an illusion of thread-safety (enough to make some programmers careless) without dealing with the real decisions of which operations need to be performed in an atomic fashion for any particular situation.



回答3:

I want to call attention to just how cool the solution from Chris Jester-Young is. I've refactored it into a simple static function that I've been successfully using which I've included below. Thanks Chris!

/**
 * Utility that can take any object that implements a given interface and returns
 * a proxy that implements the same interface and synchronizes all calls that are
 * delegated to the given object. From Chris Jester-Young, http://about.me/cky
 * @param interfaceClass The interface to synchronize. Use MyInterface.class.
 * @param object The object to synchronize that implements the given interface class.
 * @return A synchronized proxy object that delegates to the given object.
 */
public static <T> T makeSynchronized(Class<T> interfaceClass, final T object) {
    return interfaceClass.cast(
        Proxy.newProxyInstance(
            object.getClass().getClassLoader(),
            new Class<?>[]{interfaceClass},
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    synchronized (object) {
                        return method.invoke(object, args);
                    }
                }
            }
        )
    );
}


回答4:

The overhead from reflection would also reduce the speedup that you'd get by threading your code...