Java synchronized method

45,651

Solution 1

First of all, forget about synchronized methods. A so-called synchronized method...

synchronized AnyType foobar(...) {
    doSomething();
}

Is nothing but a shortcut way of writing this:

AnyType foobar(...) {
    synchronized(this) {
        doSomething();
    }
}

There is nothing special about the method in either case. What is special is the synchronized block, and what a synchronized block does is very simple. When the JVM executes this:

synchronized(foo) {
    doSomething();
}

It first evaluates the expression foo. The result must be an object reference. Then it locks the object, performs the body of the synchronized block, and then it unlocks the object.

But what does locked mean? It may mean less than you think. It does not prevent other threads from using the object. It doesn't prevent them from accessing the object's fields or, from updating its fields. The only thing that locking an object prevents is, it prevents other threads from locking the same object at the same time.

If thread A tries to enter synchronized(foo) {...} while thread B already has foo locked (either in the same synchronized block, or in a different one), then thread A will be forced to wait until thread B releases the lock.


You use synchronized blocks to protect data.

Suppose your program has some collection of objects that can be in different states. Suppose that some states make sense, but there are other states that don't make sense—invalid states.

Suppose that it is not possible for a thread to change the data from one valid state to another valid state without temporarily creating an invalid state.

If you put the code that changes the state in a synchronized(foo) block, and you put every block of code that can see the state into a synchronized block that locks the same object, foo, then you will prevent other threads from seeing the temporary invalid state.

Solution 2

Yes, other threads can access the objects used in the method; the synchronized keyword guarantees that no more than one thread at the time can execute the code of the method.

From https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html:

  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. 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.

Solution 3

In this context, synchronized simultaneously locks this method and any other method similarly marked as synchronized in your class.

Share:
45,651

Related videos on Youtube

arenaq
Author by

arenaq

Updated on July 09, 2022

Comments

  • arenaq
    arenaq almost 2 years

    Consider this code:

    public synchronized void onSignalsTimeout(List<SignalSpec> specs) {
        if (specs != null && specs.size() > 0) {
            for (SignalSpec spec : specs) {
                ParsedCANSignal timeoutedSignal = new ParsedCANSignal();
                SignalsProvider.getInstance().setSignal(spec.name, spec.parent.parent.channel, timeoutedSignal);
            }
        }
    }
    

    I've got simple question: When Thread 1 calls onSignalsTimeout method, can Thread 2 access objects that are accessed in that method?

    Can't find anywhere if 'synchronized' locks only access to this method or access to all objects used in this method.

  • arenaq
    arenaq almost 9 years
    So basicaly, if I would have 2 synchronized methods accessing one data structure and called one from one thread and the other from 2nd thread, synchronized would be completely useless?
  • Bathsheba
    Bathsheba almost 9 years
    You could arrange things so that the data structure can only be accessed by calling a function, which you mark as synchronized.
  • Codebender
    Codebender almost 9 years
    If 2 methods are marked synchronized, thread1 cannot access method1 while thread2 is executing method2?
  • arenaq
    arenaq almost 9 years
    But I can still access other (synchronized) methods of the object, when the one is been executed by another thread, right?
  • arenaq
    arenaq almost 9 years
    Are you sure about this? I cannot access other methods of one object, when someone is already executing one that I dont care about?
  • Bathsheba
    Bathsheba almost 9 years
    Yup. synchronsized used as above locks the this object's monitor. Individual method locking requires a different technique.
  • Andrea Iacono
    Andrea Iacono almost 9 years
    no, as Bathsheba already wrote, all the methods marked as synchronized in the class refer to the instance of the object for the monitor, so when one of the methods is executed, the lock on the monitor is taken and any other thread has to wait for its release to execute any method marked as synchronized.
  • arenaq
    arenaq almost 9 years
    Consider instance of one object (my example method is from singleton). This object has method1 and method2, both are synchronized. When one thread call method1 on this singleton class, can another thread call method2 or at least method3 that is not synchronized?
  • Andrea Iacono
    Andrea Iacono almost 9 years
    When one thread call method1 on the unique instance of this singleton class, no other thread can access both method1 and method2 until the first thread is done; method3 (which is not synchronized) can be accessed from any thread in any moment, even if there's a lock active on the instance (that means event if another thread is executing any of the synchronized methods).
  • arenaq
    arenaq almost 9 years
    Your explanation is very nice and easy to understand. Since you went into more detail, I must ask... where will other threads be suspended (waiting) for unlock, when a thread locks the object? I know its probably 'debugging' question, but when I suspended all threads during my deadlock I was confused, because I found two threads both executing the same synchronized method - I would expect one at the beginning and one waiting at the beginning of another synchronized method (to create a loop).
  • Solomon Slow
    Solomon Slow almost 9 years
    @arenaq Where? as in what would a debugger show you? I don't know. I haven't looked at much Java code in debuggers. I'm more of a C programmer. Synchronization is not an intrinsic language feature in C, so in C, the debugger shows the thread stopped in a synchronization system call, from inside a call to a synchronization library function, from somewhere in my code. The Java debuggers I have used don't show system calls or the inner workings of the JVM, and I don't recall ever inspecting the stack of a Java thread that was waiting to acquire a lock.
  • arenaq
    arenaq almost 9 years
    Forget it, its unrelated Q anyway... should be a new topic.
  • GhostCat
    GhostCat almost 5 years
    Unrelated: you have some content, and I am very much in support for your efforts to educate ourselves on proper use of meaningful terminology!
  • Raj
    Raj over 2 years
    I'm not sure if this statement is true ' It may mean less than you think. It does not prevent other threads from using the object. It doesn't prevent them from accessing the object's fields or, from updating its fields' .. just wondering if a different thread is updating a variable inside the synchronized block, how can we avoid that udpate?
  • Solomon Slow
    Solomon Slow over 2 years
    @Raj, If there's some data that you want to prevent multiple threads from accessing at the same time, create a final Object my_data_lock=new Object(), and write your code so that it only ever accesses the data while inside synchronized(my_data_lock). Since Java only ever allows one thread to be synchronized on a given object at any one moment in time, only one thread will ever access the data at any one moment in time.
  • Raj
    Raj over 2 years
    Thanks for the clarification @SolomonSlow