Avoid synchronized(this) in Java?

后端 未结 22 1436
予麋鹿
予麋鹿 2020-11-22 01:23

Whenever a question pops up on SO about Java synchronization, some people are very eager to point out that synchronized(this) should be avoided. Instead, they c

22条回答
  •  余生分开走
    2020-11-22 01:42

    While I agree about not adhering blindly to dogmatic rules, does the "lock stealing" scenario seem so eccentric to you? A thread could indeed acquire the lock on your object "externally"(synchronized(theObject) {...}), blocking other threads waiting on synchronized instance methods.

    If you don't believe in malicious code, consider that this code could come from third parties (for instance if you develop some sort of application server).

    The "accidental" version seems less likely, but as they say, "make something idiot-proof and someone will invent a better idiot".

    So I agree with the it-depends-on-what-the-class-does school of thought.


    Edit following eljenso's first 3 comments:

    I've never experienced the lock stealing problem but here is an imaginary scenario:

    Let's say your system is a servlet container, and the object we're considering is the ServletContext implementation. Its getAttribute method must be thread-safe, as context attributes are shared data; so you declare it as synchronized. Let's also imagine that you provide a public hosting service based on your container implementation.

    I'm your customer and deploy my "good" servlet on your site. It happens that my code contains a call to getAttribute.

    A hacker, disguised as another customer, deploys his malicious servlet on your site. It contains the following code in the init method:

    synchronized (this.getServletConfig().getServletContext()) {
       while (true) {}
    }
    

    Assuming we share the same servlet context (allowed by the spec as long as the two servlets are on the same virtual host), my call on getAttribute is locked forever. The hacker has achieved a DoS on my servlet.

    This attack is not possible if getAttribute is synchronized on a private lock, because 3rd-party code cannot acquire this lock.

    I admit that the example is contrived and an oversimplistic view of how a servlet container works, but IMHO it proves the point.

    So I would make my design choice based on security consideration: will I have complete control over the code that has access to the instances? What would be the consequence of a thread's holding a lock on an instance indefinitely?

提交回复
热议问题