Multiple Threads calling static helper method

前端 未结 7 653
孤街浪徒
孤街浪徒 2021-02-08 03:05

I have a web application running on Tomcat.

There are several calculations that need to be done on multiple places in the web application. Can I make those calculations

相关标签:
7条回答
  • 2021-02-08 03:20

    If you are worried about synchronization and thread safety, don't use static helpers. Create a normal class with your helper methods and create an instance upon servlet request. Keep it simple :-)

    0 讨论(0)
  • 2021-02-08 03:29

    If you don't have to share it you can make it thread local, then it doesn't have to be thread safe.

    public class Helper {
    
    private static final ThreadLocal<SomeObject> obj = new ThreadLocal<SomeObject>() {
        public SomeObject initialValue() {
            return enw SomeObject();
        }
    }
    
    public static void changeMember() {
        Helper.obj.get().changeValue();
    }
    
    public static String readMember() {
        Helper.obj.get().readValue();
    }
    
    }
    
    0 讨论(0)
  • 2021-02-08 03:31

    You should capture the calculations in a class, and create an instance of the class for each thread. What you have now is not threadsafe, as you are aware, and to make it threadsafe you will have to synchronize on the static resource/the methods that access that static resource, which will cause blocking.

    Note that there are patterns to help you with this. You can use the strategy pattern (in its canonical form, the strategy must be chosen at runtime, which might or might not apply here) or a variant. Just create a class for each calculation with an execute method (and an interface that has the method), and pass a context object to execute. The context holds all the state of the calculation. One strategy instance per thread, with its context, and you shouldn't have any issues.

    0 讨论(0)
  • 2021-02-08 03:31

    I'll sum up here what has been said in the comments to the Matt Ball's answer, since it got pretty long at the end and the message gets lost: and the message was

    in a shared environment like a web/application server you should try very hard to find a solution without synchronizing. Using static helpers synchronized on static object might work well enough for stand alone application with a single user in front of the screen, in a multiuser/multiapplication scenario doing this would most probably end in a very poor performance - it would effectively mean serializing access to your application, all users would have to wait on the same lock. You might not notice the problem for a long time: if the calculation are fast enough and load is evenly distributed.

    But then all of a sudden all your users might try to go through the calculation at 9am and you app will stop to work! I mean not really stop, but they all would block on the lock and make a huge queue.

    Now regardless the necessity of a shared state, since you originally named calculations as subject of synchronization: do their results need to be shared? Or are those calculations specific to a user/session? In the latter case a ThreadLocal as per Peter Lawrey would be enough. Otherwise I'd say for overall performance it would be better to duplicate the calculations for everybody needing them in order not to synchronize (depends on the cost).

    Session management should also be better left to the container: it has been optimized to handle them efficiently, if necessary including clustering etc. I doubt one could make better solution without investing lot of work and making lots of bugs on the way there. But as Matt Ball has stated it should be better asked separately.

    0 讨论(0)
  • 2021-02-08 03:42

    can i make those calculations static helper functions? if the server has enough processor cores, can multiple calls to that static function (resulting from multiple requests to different servlets) run parallel?

    Yes, and yes.

    do i have to make the whole static functions synchronized

    That will work.

    or just the block where Helper.obj is used

    That will also work.

    if i should use a block, what object should i use to lock it?

    Use a static Object:

    public class Helper {
    
        private static SomeObject obj;
        private static final Object mutex = new Object();
    
        public static void changeMember() {
            synchronized (mutex) {
                obj.changeValue();
            }
        }
    
        public static String readMember() {
            synchronized (mutex) {
                obj.readValue();
            }
        }
    }
    

    Ideally, though, you'd write the helper class to be immutable (stateless or otherwise) so that you just don't have to worry about thread safety.

    0 讨论(0)
  • 2021-02-08 03:43

    In the first case you don't have to worry about threading issues, because the variables are local to each thread. You correctly identify the problem in the second case, though, because multiple threads will be reading/writing the same object. Synchronizing on the methods will work, as would synchronized blocks.

    0 讨论(0)
提交回复
热议问题