Avoid synchronized(this) in Java?

后端 未结 22 1443
予麋鹿
予麋鹿 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 02:02

    1. Make your data immutable if it is possible ( final variables)
    2. If you can't avoid mutation of shared data across multiple threads, use high level programming constructs [e.g. granular Lock API ]

    A Lock provides exclusive access to a shared resource: only one thread at a time can acquire the lock and all access to the shared resource requires that the lock be acquired first.

    Sample code to use ReentrantLock which implements Lock interface

     class X {
       private final ReentrantLock lock = new ReentrantLock();
       // ...
    
       public void m() {
         lock.lock();  // block until condition holds
         try {
           // ... method body
         } finally {
           lock.unlock()
         }
       }
     }
    

    Advantages of Lock over Synchronized(this)

    1. The use of synchronized methods or statements forces all lock acquisition and release to occur in a block-structured way.

    2. Lock implementations provide additional functionality over the use of synchronized methods and statements by providing

      1. A non-blocking attempt to acquire a lock (tryLock())
      2. An attempt to acquire the lock that can be interrupted (lockInterruptibly())
      3. An attempt to acquire the lock that can timeout (tryLock(long, TimeUnit)).
    3. A Lock class can also provide behavior and semantics that is quite different from that of the implicit monitor lock, such as

      1. guaranteed ordering
      2. non-re entrant usage
      3. Deadlock detection

    Have a look at this SE question regarding various type of Locks:

    Synchronization vs Lock

    You can achieve thread safety by using advanced concurrency API instead of Synchronied blocks. This documentation page provides good programming constructs to achieve thread safety.

    Lock Objects support locking idioms that simplify many concurrent applications.

    Executors define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.

    Concurrent Collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.

    Atomic Variables have features that minimize synchronization and help avoid memory consistency errors.

    ThreadLocalRandom (in JDK 7) provides efficient generation of pseudorandom numbers from multiple threads.

    Refer to java.util.concurrent and java.util.concurrent.atomic packages too for other programming constructs.

提交回复
热议问题