Is there an advantage to use a Synchronized Method instead of a Synchronized Block?

后端 未结 23 1990
北荒
北荒 2020-11-22 04:29

Can any one tell me the advantage of synchronized method over synchronized block with an example?

23条回答
  •  忘了有多久
    2020-11-22 04:54

    Synchronized method

    Synchronized methods have two effects.
    First, when one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

    Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

    Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.

    Synchronized Statement

    Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock: Most often I use this to synchronize access to a list or map but I don't want to block access to all methods of the object.

    Q: Intrinsic Locks and Synchronization Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

    Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

    package test;
    
    public class SynchTest implements Runnable {  
        private int c = 0;
    
        public static void main(String[] args) {
            new SynchTest().test();
        }
    
        public void test() {
            // Create the object with the run() method
            Runnable runnable = new SynchTest();
            Runnable runnable2 = new SynchTest();
            // Create the thread supplying it with the runnable object
            Thread thread = new Thread(runnable,"thread-1");
            Thread thread2 = new Thread(runnable,"thread-2");
    //      Here the key point is passing same object, if you pass runnable2 for thread2,
    //      then its not applicable for synchronization test and that wont give expected
    //      output Synchronization method means "it is not possible for two invocations
    //      of synchronized methods on the same object to interleave"
    
            // Start the thread
            thread.start();
            thread2.start();
        }
    
        public synchronized  void increment() {
            System.out.println("Begin thread " + Thread.currentThread().getName());
            System.out.println(this.hashCode() + "Value of C = " + c);
    //      If we uncomment this for synchronized block, then the result would be different
    //      synchronized(this) {
                for (int i = 0; i < 9999999; i++) {
                    c += i;
                }
    //      }
            System.out.println("End thread " + Thread.currentThread().getName());
        }
    
    //    public synchronized void decrement() {
    //        System.out.println("Decrement " + Thread.currentThread().getName());
    //    }
    
        public int value() {
            return c;
        }
    
        @Override
        public void run() {
            this.increment();
        }
    }
    

    Cross check different outputs with synchronized method, block and without synchronization.

提交回复
热议问题