0

I have a class ClassA that has a public void doSomething() method. This ClassA is widely used in different applications; some require synchronized and others do not. It is also the case that I do not want the (tiny, but non-zero) performance hit associated with calling a synchronized method when I do not need this.

Suppose that ClassB will call doSomething() and requires that this is synchronized, yet ClassC does not require this. What are the ways that I can achieve this in the design of my program?

Is it sufficient to have the method in ClassB:

private synchronized void doSomething() {
    this.classAInstance.doSomething();
}

thus avoiding the need to specify ClassC's doSomething() as synchronized?

user2763361
  • 3,789
  • 11
  • 45
  • 81
  • 4
    there is a fundamental display of lack of comprehension on what `synchronized` does in the question. You either need currency safety or you don't, there is no sometimes ... –  Mar 26 '14 at 02:40
  • @JarrodRoberson Why would I always need it? – user2763361 Mar 26 '14 at 02:42
  • 2
    Because you need it some times. – Sotirios Delimanolis Mar 26 '14 at 02:43
  • @SotiriosDelimanolis Could you please give a slightly more detailed answer as I am still new to this topic. – user2763361 Mar 26 '14 at 02:44
  • Your code is compiled. You can't some times have synchronized and some times not. It's either always or never. – Sotirios Delimanolis Mar 26 '14 at 02:45
  • @SotiriosDelimanolis What I want is for the method to be always synchronized when I am using an application that uses `ClassB`, whereas never synchronized when I am using a different application that uses `ClassC`. But I want to achieve this without needing to make two copies of `ClassA` or to have two different methods (one synchrnized and one not in `ClassA`). TWo separate applications, one always needing sync and the other never needing it, but both needing `ClassA`. – user2763361 Mar 26 '14 at 02:46
  • 1
    @user2763361 I can think of exactly one use case for this, but I honestly want to ask if you can, because I'm really skeptical you need this design to begin with. – djechlin Mar 26 '14 at 02:50
  • Yes, you can do as you suggest. But do keep in mind that the specific object you synchronize on is critical. All mutually exclusive actions must reference the same object for synchronization. – Hot Licks Mar 26 '14 at 03:03
  • 2
    @JarrodRoberson et al - The OP is saying that he uses the same class in _multiple disparate projects_. Some of those projects are for multi-threaded applications, and some are not; therefore, he only needs a synchronized object some of the time. – DaoWen Mar 26 '14 at 03:16
  • @DaoWen: if that's the case he shouldn't be worried about single-threaded apps, since the synchronization will be pretty much a no-op when there is no contention. – vanza Mar 26 '14 at 03:24
  • @vanza As I said, I do not want the tiny but non-zero performance hit associated with calling sync when not needed. – user2763361 Mar 26 '14 at 03:25
  • 1
    @user2763361: unless you have proven that it's an actual problem, you're just trying to solve a non-existant problem. – vanza Mar 26 '14 at 03:25
  • @vanza It's not non-existent. Please google on the performance hit associated with this. – user2763361 Mar 26 '14 at 03:26
  • 1
    @user2763361: Google says a lot of things... JVM engineers will disagree with a lot of them. – vanza Mar 26 '14 at 03:27
  • @vanza - If that were true then the JDK wouldn't need to include both [StringBuffer](http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuffer.html) (synchronized) and [StringBuilder](http://docs.oracle.com/javase/7/docs/api/java/lang/StringBuilder.html) (unsynchronized). The JavaDoc specifically says to avoid use StringBuffer when possible for performance reasons, and plenty of other people have measured a [performance](http://stackoverflow.com/a/2771852/1427124) [gap](http://www.journaldev.com/137/stringbuffer-vs-stringbuilder-benchmarking) between the two. – DaoWen Mar 26 '14 at 03:51
  • @DaoWen: I'm not saying synchronized is free. I'm saying that in the vast majority of cases, when there is no contention, its overhead is negligible when compared to the rest of the program. StringBuffer is an exception because of its usage pattern (lots of calls that do very little work, as opposed to few calls that do a lot of work). – vanza Mar 26 '14 at 04:15
  • @vanza Which is basically my issue. – user2763361 Mar 26 '14 at 04:50
  • @user2763361: so, again, the question: have you measured the overhead and proved that it's measurable and noticeable? Otherwise, it sounds like you're drawing conclusions based on use cases that may not match yours. – vanza Mar 26 '14 at 05:00
  • 1
    @vanza The time it would take to microbenchmark this I could already have fixed it 50 times over. – user2763361 Mar 26 '14 at 05:29
  • @user2763361: microbenchmarks are, at best, misleading. You should profile your app. A 50% gain in a microbenchmark might only translate to a 1% gain in your app, which does not justify the extra code / test / maintenance overhead of different code for each code path. But it's your time, you choose how to best use it... – vanza Mar 26 '14 at 16:32

2 Answers2

4

When you have a need to use the same class with and without synchronization, a common approach is to make an interface, and provide two implementations - a non-synchronized class with the actual implementation, and a thin wrapper that adds synchronization.

Here is a simple example: suppose you are building a class with two operations - getSomething and setSomething. The interface may look like this:

interface Demo {
    void setSomething(Something value);
    Something getSomething();
}

Now the non-synchronized implementation may look like this:

class DemoImpl implements Demo {
    private Something theSomething;
    public void setSomething(Something value) {
        theSomething = value;
    }
    public Something getSomething() {
        return theSomething;
    }
}

Finally, the synchronized implementation:

class SyncDemoImpl implements Demo {
    private DemoImpl impl = new DemoImpl();
    public synchronized void setSomething(Something value) {
        impl.setSomething(value);
    }
    public synchronized Something getSomething() {
        return impl.getSomething();
    }
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Or more generally, a threadsafe implementation and a nonthreadsafe implementation, that may be quite different depending on patterns used. – djechlin Mar 26 '14 at 02:52
2

Bear in mind that this is purely an academical exercise. I don't see any practical reason why a resource should need a selective synchronized access. Either you need it, or you don't. If you have to do this, you are setting yourself up for long hours of troubleshooting few months down the line. If I could, I would rethink the design.

So, You say - 'some require synchronized and others do not'

I take that means you know exactly each and every part of your code that needs Synchronized access, and can differentiate it from those that need to save this overhead. If so: You have two options:

  1. Get rid of the synchronized modifier of the method all together and get all the callers that need synchronization to synchronize before the call is made. Thus:

    synchronized (classAInstance){
        classAInstance.doSomething();  // the doSomething() is non-synchronised
    }
    

Those parts in code that call this method and do not need synchronized access can call the method directly.

  1. Make two methods, one that is synchronized and other that is not synchronized. Change the callers to call based on the way you want the access to be controlled.
Anup Puranik
  • 165
  • 1
  • 10