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

23

421

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

Mot answered 22/2, 2009 at 3:13 Comment(3)
This is somewhat of a duplicate of Avoid synchronized(this) in Java? and In Java critical sections, what should I synchronize on?Flounce
Exact duplicate of: #443064 and #416683Denadenae
@Flounce this question is entirely different from #443064Sammiesammons
L
451

Can anyone tell me the advantage of the synchronized method over the synchronized block with an example? Thanks.

There is not a clear advantage of using synchronized method over the block.

Perhaps the only one ( but I wouldn't call it an advantage ) is you don't need to include the object reference this.

Method:

public synchronized void method() { // blocks "this" from here.... 
    ...
    ...
    ...
} // to here

Block:

public void method() { 
    synchronized( this ) { // blocks "this" from here .... 
        ....
        ....
        ....
    }  // to here...
}

See? No advantage at all.

Blocks do have advantages over methods though, mostly in flexibility because you can use another object as lock whereas syncing the method would lock the entire object.

Compare:

// locks the whole object
... 
private synchronized void someInputRelatedWork() {
    ... 
}
private synchronized void someOutputRelatedWork() {
    ... 
}

vs.

// Using specific locks
Object inputLock = new Object();
Object outputLock = new Object();

private void someInputRelatedWork() {
    synchronized(inputLock) { 
        ... 
    } 
}
private void someOutputRelatedWork() {
    synchronized(outputLock) { 
        ... 
    }
}

Also if the method grows you can still keep the synchronized section separated:

 private void method() {
     ... code here
     ... code here
     ... code here
    synchronized( lock ) { 
        ... very few lines of code here
    }
     ... code here
     ... code here
     ... code here
     ... code here
}
Lawerencelawes answered 22/2, 2009 at 3:36 Comment(13)
A benefit to the consumer of the API is that using the synchronized keyword in the method declaration also explicitly declares that the method synchronizes on the object instance and is (presumably) thread-safe.Ballarat
so "this" object get locked in less time - so if possible, sync in block rather that the entire method:)Spark
I know this is an old question but synchronizing on "this" is considered in some circles to be an anti-pattern. The unintended consequence is that outside of the class someone can lock on an object reference that is equal to "this" and prevent other threads from passing the barriers within the class potentially creating a deadlock situation. Creating a "private final Object = new Object();" variable purely for locking purposes is the often used solution. Here's another question relating directly to this issue.Fimble
@Fimble Yes, but synchronized methods implicitly lock on thisBlacklist
@Cruncher, I'm not quite sure what your comment is saying. I was pointing out that you have to be aware of the potentially unintended consequences of locking on this regardless of the mechanism (explicit synchronized(this) vs a synchronized method). Again, please see the question I referenced in my previous comment and read through the solutions. You will see numerous up-voted solutions that detail the dangers synchronizing on this.Fimble
@Fimble I agree with you completely. It's just that, this answer is showing the difference between sycnhronized(this) vs a synchronized method. Then the point you made was a negative for synchronized(this) which implicitly seems like you're supporting a synchronized method, which has the same problems. I'd also like to add that I essentially, exclusively use private finals for locking purposes.Blacklist
...Of note as well is that the synchronized block uses a fair bit more bytecode than a synchronized method ibm.com/developerworks/ibm/library/it-haggar_bytecodeCraniotomy
"whereas syncing the method would lock the complete class." This is not correct. It doesn't lock the complete class, but the complete instance. Multiple objects from the same class hold all their own lock. :) GreetsGrier
Something interesting about this is that using a synchronized method will cause the generated bytecode to have 1 less instruction, since methods have a synchronized bit baked into their signature. Since the length of the bytecode is a factor in whether a method gets in-lined, moving the block to the method signature could be the difference in decision. In theory anyway. I wouldn't base a design decision on a single bytecode instruction being saved, that seems like a terrible idea. But still, it is a difference. =)Glucoside
@corsiKa: you save more than one instruction. A synchronized block is implemented using two instructions, monitorenter and monitorexit, plus an exception handler which ensures that monitorexit is called even in the exceptional case. That’s all saved when using a synchronized method.Giffie
@Ballarat Agreed. Declaring the method synchronized is a more elegant way to communicate the intentions of the programmer. One can always factor out a smaller function if one wants to limit the duration of the lock.Remus
@TrudleR Not only do synchronized methods not lock the whole class, but they don't lock the whole instance either. Unsynchronized methods in the class may still proceed on the instance.Remus
@WarrenDew Right. Only the syncronized methods are locked. If there are fields you use within synced methods that are accessed by unsynced methods, you can run into race conditions.Grier
P
143

The only real difference is that a synchronized block can choose which object it synchronizes on. A synchronized method can only use 'this' (or the corresponding Class instance for a synchronized class method). For example, these are semantically equivalent:

synchronized void foo() {
  ...
}

void foo() {
    synchronized (this) {
      ...
    }
}

The latter is more flexible since it can compete for the associated lock of any object, often a member variable. It's also more granular because you could have concurrent code executing before and after the block but still within the method. Of course, you could just as easily use a synchronized method by refactoring the concurrent code into separate non-synchronized methods. Use whichever makes the code more comprehensible.

Pepsinogen answered 22/2, 2009 at 3:26 Comment(2)
The latter can also have merit if not all of the code in foo() needs to be synchronised.Kenzie
This is true, but not what "Warrior" asked: "The advantage of synchronized method" there is none.Lawerencelawes
B
78

Synchronized Method

Pros:

  • Your IDE can indicate the synchronized methods.
  • The syntax is more compact.
  • Forces to split the synchronized blocks to separate methods.

Cons:

  • Synchronizes to this and so makes it possible to outsiders to synchronize to it too.
  • It is harder to move code outside the synchronized block.

Synchronized block

Pros:

  • Allows using a private variable for the lock and so forcing the lock to stay inside the class.
  • Synchronized blocks can be found by searching references to the variable.

Cons:

  • The syntax is more complicated and so makes the code harder to read.

Personally I prefer using synchronized methods with classes focused only to the thing needing synchronization. Such class should be as small as possible and so it should be easy to review the synchronization. Others shouldn't need to care about synchronization.

Brockbrocken answered 22/2, 2009 at 7:31 Comment(1)
When you say "stay inside the class" do you mean "stay inside the object", or am I missing something?Wiggle
A
36

The main difference is that if you use a synchronized block you may lock on an object other than this which allows to be much more flexible.

Assume you have a message queue and multiple message producers and consumers. We don't want producers to interfere with each other, but the consumers should be able to retrieve messages without having to wait for the producers. So we just create an object

Object writeLock = new Object();

And from now on every time a producers wants to add a new message we just lock on that:

synchronized(writeLock){
  // do something
}

So consumers may still read, and producers will be locked.

Avifauna answered 22/2, 2009 at 3:32 Comment(1)
Your example is limited to non destructive reads. If the read removes the message from the queue this will fail if it is done at the some time as a producer writes to the queue.Eppes
F
31

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.

Fortress answered 18/4, 2011 at 21:15 Comment(3)
+1 for being the only one so far to mention that constructors cannot be synchronized. That is, in a constructor you really have only one option: Synchronized blocks.Tallyman
I tested your code as directed but C is always 0, then -2024260031 and the only thing that changes it the hash code. What behavior should be seen?Annelieseannelise
You should have quoted below articles from which the content has been provided: docs.oracle.com/javase/tutorial/essential/concurrency/… and docs.oracle.com/javase/tutorial/essential/concurrency/…Jazmin
T
28

Note: static synchronized methods and blocks work on the Class object.

public class MyClass {
   // locks MyClass.class
   public static synchronized void foo() {
// do something
   }

   // similar
   public static void foo() {
      synchronized(MyClass.class) {
// do something
      }
   }
}
Testimony answered 22/2, 2009 at 3:30 Comment(0)
T
18

When java compiler converts your source code to byte code, it handles synchronized methods and synchronized blocks very differently.

When the JVM executes a synchronized method, the executing thread identifies that the method's method_info structure has the ACC_SYNCHRONIZED flag set, then it automatically acquires the object's lock, calls the method, and releases the lock. If an exception occurs, the thread automatically releases the lock.

Synchronizing a method block, on the other hand, bypasses the JVM's built-in support for acquiring an object's lock and exception handling and requires that the functionality be explicitly written in byte code. If you read the byte code for a method with a synchronized block, you will see more than a dozen additional operations to manage this functionality.

This shows calls to generate both a synchronized method and a synchronized block:

public class SynchronizationExample {
    private int i;

    public synchronized int synchronizedMethodGet() {
        return i;
    }

    public int synchronizedBlockGet() {
        synchronized( this ) {
            return i;
        }
    }
}

The synchronizedMethodGet() method generates the following byte code:

0:  aload_0
1:  getfield
2:  nop
3:  iconst_m1
4:  ireturn

And here's the byte code from the synchronizedBlockGet() method:

0:  aload_0
1:  dup
2:  astore_1
3:  monitorenter
4:  aload_0
5:  getfield
6:  nop
7:  iconst_m1
8:  aload_1
9:  monitorexit
10: ireturn
11: astore_2
12: aload_1
13: monitorexit
14: aload_2
15: athrow

One significant difference between synchronized method and block is that, Synchronized block generally reduce scope of lock. As scope of lock is inversely proportional to performance, its always better to lock only critical section of code. One of the best example of using synchronized block is double checked locking in Singleton pattern where instead of locking whole getInstance() method we only lock critical section of code which is used to create Singleton instance. This improves performance drastically because locking is only required one or two times.

While using synchronized methods, you will need to take extra care if you mix both static synchronized and non-static synchronized methods.

Thalamus answered 21/4, 2014 at 8:53 Comment(2)
If we look at bytecode synchronized method bytecode is more compact and simple, so why its not faster that synchronized block ?Dominion
@Dominion Note that this is bytecode which is further "compiled" by the JVM. The JVM will add in the necessary monitorenter and monitorexit before running the code.Nuncia
C
12

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.

In the following code one thread modifying the list will not block waiting for a thread that is modifying the map. If the methods were synchronized on the object then each method would have to wait even though the modifications they are making would not conflict.

private List<Foo> myList = new ArrayList<Foo>();
private Map<String,Bar) myMap = new HashMap<String,Bar>();

public void put( String s, Bar b ) {
  synchronized( myMap ) {
    myMap.put( s,b );
    // then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public void hasKey( String s, ) {
  synchronized( myMap ) {
    myMap.hasKey( s );
  }
}

public void add( Foo f ) {
  synchronized( myList ) {
    myList.add( f );
// then some thing that may take a while like a database access or RPC or notifying listeners
  }
}

public Thing getMedianFoo() {
  Foo med = null;
  synchronized( myList ) {
    Collections.sort(myList);
    med = myList.get(myList.size()/2); 
  }
  return med;
}
Cuff answered 22/2, 2009 at 7:4 Comment(0)
V
7

With synchronized blocks, you can have multiple synchronizers, so that multiple simultaneous but non-conflicting things can go on at the same time.

Verbalize answered 22/2, 2009 at 3:19 Comment(0)
F
6

Synchronized methods can be checked using reflection API. This can be useful for testing some contracts, such as all methods in model are synchronized.

The following snippet prints all the synchronized methods of Hashtable:

for (Method m : Hashtable.class.getMethods()) {
        if (Modifier.isSynchronized(m.getModifiers())) {
            System.out.println(m);
        }
}
Foresee answered 10/12, 2012 at 14:25 Comment(0)
D
5

Important note on using the synchronized block: careful what you use as lock object!

The code snippet from user2277816 above illustrates this point in that a reference to a string literal is used as locking object. Realize that string literals are automatically interned in Java and you should begin to see the problem: every piece of code that synchronizes on the literal "lock", shares the same lock! This can easily lead to deadlocks with completely unrelated pieces of code.

It is not just String objects that you need to be careful with. Boxed primitives are also a danger, since autoboxing and the valueOf methods can reuse the same objects, depending on the value.

For more information see: https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused

Darceydarci answered 12/8, 2013 at 11:41 Comment(0)
D
5

Often using a lock on a method level is too rude. Why lock up a piece of code that does not access any shared resources by locking up an entire method. Since each object has a lock, you can create dummy objects to implement block level synchronization. The block level is more efficient because it does not lock the whole method.

Here some example

Method Level

class MethodLevel {

  //shared among threads
SharedResource x, y ;

public void synchronized method1() {
   //multiple threads can't access
}
public void synchronized method2() {
  //multiple threads can't access
}

 public void method3() {
  //not synchronized
  //multiple threads can access
 }
}

Block Level

class BlockLevel {
  //shared among threads
  SharedResource x, y ;

  //dummy objects for locking
  Object xLock = new Object();
  Object yLock = new Object();

    public void method1() {
     synchronized(xLock){
    //access x here. thread safe
    }

    //do something here but don't use SharedResource x, y
    // because will not be thread-safe
     synchronized(xLock) {
       synchronized(yLock) {
      //access x,y here. thread safe
      }
     }

     //do something here but don't use SharedResource x, y
     //because will not be thread-safe
    }//end of method1
 }

[Edit]

For Collection like Vector and Hashtable they are synchronized when ArrayList or HashMap are not and you need set synchronized keyword or invoke Collections synchronized method:

Map myMap = Collections.synchronizedMap (myMap); // single lock for the entire map
List myList = Collections.synchronizedList (myList); // single lock for the entire list
Developing answered 30/9, 2013 at 6:43 Comment(0)
J
5

The only difference : synchronized blocks allows granular locking unlike synchronized method

Basically synchronized block or methods have been used to write thread safe code by avoiding memory inconsistency errors.

This question is very old and many things have been changed during last 7 years. New programming constructs have been introduced for thread safety.

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.

Better replacement for synchronized is ReentrantLock, which uses Lock API

A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.

Example with locks:

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

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

Refer to this related question too:

Synchronization vs Lock

Jazmin answered 21/5, 2016 at 18:12 Comment(0)
C
4

Synchronized method is used for lock all the objects Synchronized block is used to lock specific object

Capsulate answered 14/7, 2010 at 6:35 Comment(0)
O
3

In general these are mostly the same other than being explicit about the object's monitor that's being used vs the implicit this object. One downside of synchronized methods that I think is sometimes overlooked is that in using the "this" reference to synchronize on you are leaving open the possibility of external objects locking on the same object. That can be a very subtle bug if you run into it. Synchronizing on an internal explicit Object or other existing field can avoid this issue, completely encapsulating the synchronization.

Outwork answered 22/2, 2009 at 20:28 Comment(0)
J
2

As already said here synchronized block can use user-defined variable as lock object, when synchronized function uses only "this". And of course you can manipulate with areas of your function which should be synchronized. But everyone says that no difference between synchronized function and block which covers whole function using "this" as lock object. That is not true, difference is in byte code which will be generated in both situations. In case of synchronized block usage should be allocated local variable which holds reference to "this". And as result we will have a little bit larger size for function (not relevant if you have only few number of functions).

More detailed explanation of the difference you can find here: http://www.artima.com/insidejvm/ed2/threadsynchP.html

Jackscrew answered 16/7, 2013 at 8:43 Comment(0)
K
2

As a practical matter, the advantage of synchronized methods over synchronized blocks is that they are more idiot-resistant; because you can't choose an arbitrary object to lock on, you can't misuse the synchronized method syntax to do stupid things like locking on a string literal or locking on the contents of a mutable field that gets changed out from under the threads.

On the other hand, with synchronized methods you can't protect the lock from getting acquired by any thread that can get a reference to the object.

So using synchronized as a modifier on methods is better at protecting your cow-orkers from hurting themselves, while using synchronized blocks in conjunction with private final lock objects is better at protecting your own code from the cow-orkers.

Kironde answered 28/10, 2015 at 18:8 Comment(0)
A
2

In case of synchronized methods, lock will be acquired on an Object. But if you go with synchronized block you have an option to specify an object on which the lock will be acquired.

Example :

    Class Example {
    String test = "abc";
    // lock will be acquired on String  test object.
    synchronized (test) {
        // do something
    }

   lock will be acquired on Example Object
   public synchronized void testMethod() {
     // do some thing
   } 

   }
Adiathermancy answered 13/12, 2015 at 11:54 Comment(0)
D
2

I know this is an old question, but with my quick read of the responses here, I didn't really see anyone mention that at times a synchronized method may be the wrong lock.
From Java Concurrency In Practice (pg. 72):

public class ListHelper<E> {
  public List<E> list = Collections.syncrhonizedList(new ArrayList<>());
...

public syncrhonized boolean putIfAbsent(E x) {
 boolean absent = !list.contains(x);
if(absent) {
 list.add(x);
}
return absent;
}

The above code has the appearance of being thread-safe. However, in reality it is not. In this case the lock is obtained on the instance of the class. However, it is possible for the list to be modified by another thread not using that method. The correct approach would be to use

public boolean putIfAbsent(E x) {
 synchronized(list) {
  boolean absent = !list.contains(x);
  if(absent) {
    list.add(x);
  }
  return absent;
}
}

The above code would block all threads trying to modify list from modifying the list until the synchronized block has completed.

Dalliance answered 8/12, 2016 at 16:47 Comment(3)
reading this book at the moment... im wondering... if that list was private instead of public and only had the putIfAbsent method, synchronized(this) would be sufficient right? the issue at hand is because the list can be modified outside that ListHelper as well?Haileyhailfellowwellmet
@Haileyhailfellowwellmet yea if the list was private and not leaked anywhere else in the class then that would be sufficient, as long as you marked every other method in the class which modifies the list as synchronized also. However, locking the whole method instead of just the List may lead to performance issues if there is a log of code that does not necessarily need to be synchronizedDalliance
that makes sense. thanks so much for answering! tbh, i've found the book quite useful in expanding my knowledge and how to approach multithreading but its also introduced a whole new world of confusion to meHaileyhailfellowwellmet
D
1

From a Java specification summary: http://www.cs.cornell.edu/andru/javaspec/17.doc.html

The synchronized statement (§14.17) computes a reference to an object; it then attempts to perform a lock action on that object and does not proceed further until the lock action has successfully completed. ...

A synchronized method (§8.4.3.5) automatically performs a lock action when it is invoked; its body is not executed until the lock action has successfully completed. If the method is an instance method, it locks the lock associated with the instance for which it was invoked (that is, the object that will be known as this during execution of the body of the method). If the method is static, it locks the lock associated with the Class object that represents the class in which the method is defined. ...

Based on these descriptions, I would say most previous answers are correct, and a synchronized method might be particularly useful for static methods, where you would otherwise have to figure out how to get the "Class object that represents the class in which the method was defined."

Edit: I originally thought these were quotes of the actual Java spec. Clarified that this page is just a summary/explanation of the spec

Douche answered 17/12, 2013 at 23:10 Comment(0)
C
1

TLDR; Neither use the synchronized modifier nor the synchronized(this){...} expression but synchronized(myLock){...} where myLock is a final instance field holding a private object.


The difference between using the synchronized modifier on the method declaration and the synchronized(..){ } expression in the method body are this:

  • The synchronized modifier specified on the method's signature
    1. is visible in the generated JavaDoc,
    2. is programmatically determinable via reflection when testing a method's modifier for Modifier.SYNCHRONIZED,
    3. requires less typing and indention compared to synchronized(this) { .... }, and
    4. (depending on your IDE) is visible in the class outline and code completion,
    5. uses the this object as lock when declared on non-static method or the enclosing class when declared on a static method.
  • The synchronized(...){...} expression allows you
    1. to only synchronize the execution of parts of a method's body,
    2. to be used within a constructor or a (static) initialization block,
    3. to choose the lock object which controls the synchronized access.

However, using the synchronized modifier or synchronized(...) {...} with this as the lock object (as in synchronized(this) {...}), have the same disadvantage. Both use it's own instance as the lock object to synchronize on. This is dangerous because not only the object itself but any other external object/code that holds a reference to that object can also use it as a synchronization lock with potentially severe side effects (performance degradation and deadlocks).

Therefore best practice is to neither use the synchronized modifier nor the synchronized(...) expression in conjunction with this as lock object but a lock object private to this object. For example:

public class MyService {
    private final lock = new Object();

    public void doThis() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }

    public void doThat() {
       synchronized(lock) {
          // do code that requires synchronous execution
        }
    }
}

You can also use multiple lock objects but special care needs to be taken to ensure this does not result in deadlocks when used nested.

public class MyService {
    private final lock1 = new Object();
    private final lock2 = new Object();

    public void doThis() {
       synchronized(lock1) {
          synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThat() and doMore().
          }
    }

    public void doThat() {
       synchronized(lock1) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doMore() may execute concurrently
        }
    }

    public void doMore() {
       synchronized(lock2) {
              // code here is guaranteed not to be executes at the same time
              // as the synchronized code in doThis().
              // doThat() may execute concurrently
        }
    }
}
Cinemascope answered 15/8, 2017 at 22:12 Comment(0)
S
1

I suppose this question is about the difference between Thread Safe Singleton and Lazy initialization with Double check locking. I always refer to this article when I need to implement some specific singleton.

Well, this is a Thread Safe Singleton:

// Java program to create Thread Safe 
// Singleton class 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

 //synchronized method to control simultaneous access 
  synchronized public static GFG getInstance()  
  { 
    if (instance == null)  
    { 
      // if instance is null, initialize 
      instance = new GFG(); 
    } 
    return instance; 
  } 
} 

Pros:

  1. Lazy initialization is possible.

  2. It is thread safe.

Cons:

  1. getInstance() method is synchronized so it causes slow performance as multiple threads can’t access it simultaneously.

This is a Lazy initialization with Double check locking:

// Java code to explain double check locking 
public class GFG  
{ 
  // private instance, so that it can be 
  // accessed by only by getInstance() method 
  private static GFG instance; 

  private GFG()  
  { 
    // private constructor 
  } 

  public static GFG getInstance() 
  { 
    if (instance == null)  
    { 
      //synchronized block to remove overhead 
      synchronized (GFG.class) 
      { 
        if(instance==null) 
        { 
          // if instance is null, initialize 
          instance = new GFG(); 
        } 

      } 
    } 
    return instance; 
  } 
} 

Pros:

  1. Lazy initialization is possible.

  2. It is also thread safe.

  3. Performance reduced because of synchronized keyword is overcome.

Cons:

  1. First time, it can affect performance.

  2. As cons. of double check locking method is bearable so it can be used for high performance multi-threaded applications.

Please refer to this article for more details:

https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/

Stevie answered 4/2, 2019 at 14:52 Comment(0)
U
-3

Synchronizing with threads. 1) NEVER use synchronized(this) in a thread it doesn't work. Synchronizing with (this) uses the current thread as the locking thread object. Since each thread is independent of other threads, there is NO coordination of synchronization. 2) Tests of code show that in Java 1.6 on a Mac the method synchronization does not work. 3) synchronized(lockObj) where lockObj is a common shared object of all threads synchronizing on it will work. 4) ReenterantLock.lock() and .unlock() work. See Java tutorials for this.

The following code shows these points. It also contains the thread-safe Vector which would be substituted for the ArrayList, to show that many threads adding to a Vector do not lose any information, while the same with an ArrayList can lose information. 0) Current code shows loss of information due to race conditions A) Comment the current labeled A line, and uncomment the A line above it, then run, method loses data but it shouldn't. B) Reverse step A, uncomment B and // end block }. Then run to see results no loss of data C) Comment out B, uncomment C. Run, see synchronizing on (this) loses data, as expected. Don't have time to complete all the variations, hope this helps. If synchronizing on (this), or the method synchronization works, please state what version of Java and OS you tested. Thank you.

import java.util.*;

/** RaceCondition - Shows that when multiple threads compete for resources 
     thread one may grab the resource expecting to update a particular 
     area but is removed from the CPU before finishing.  Thread one still 
     points to that resource.  Then thread two grabs that resource and 
     completes the update.  Then thread one gets to complete the update, 
     which over writes thread two's work.
     DEMO:  1) Run as is - see missing counts from race condition, Run severa times, values change  
            2) Uncomment "synchronized(countLock){ }" - see counts work
            Synchronized creates a lock on that block of code, no other threads can 
            execute code within a block that another thread has a lock.
        3) Comment ArrayList, unComment Vector - See no loss in collection
            Vectors work like ArrayList, but Vectors are "Thread Safe"
         May use this code as long as attribution to the author remains intact.
     /mf
*/ 

public class RaceCondition {
    private ArrayList<Integer> raceList = new ArrayList<Integer>(); // simple add(#)
//  private Vector<Integer> raceList = new Vector<Integer>(); // simple add(#)

    private String countLock="lock";    // Object use for locking the raceCount
    private int raceCount = 0;        // simple add 1 to this counter
    private int MAX = 10000;        // Do this 10,000 times
    private int NUM_THREADS = 100;    // Create 100 threads

    public static void main(String [] args) {
    new RaceCondition();
    }

    public RaceCondition() {
    ArrayList<Thread> arT = new ArrayList<Thread>();

    // Create thread objects, add them to an array list
    for( int i=0; i<NUM_THREADS; i++){
        Thread rt = new RaceThread( ); // i );
        arT.add( rt );
    }

    // Start all object at once.
    for( Thread rt : arT ){
        rt.start();
    }

    // Wait for all threads to finish before we can print totals created by threads
    for( int i=0; i<NUM_THREADS; i++){
        try { arT.get(i).join(); }
        catch( InterruptedException ie ) { System.out.println("Interrupted thread "+i); }
    }

    // All threads finished, print the summary information.
    // (Try to print this informaiton without the join loop above)
    System.out.printf("\nRace condition, should have %,d. Really have %,d in array, and count of %,d.\n",
                MAX*NUM_THREADS, raceList.size(), raceCount );
    System.out.printf("Array lost %,d. Count lost %,d\n",
             MAX*NUM_THREADS-raceList.size(), MAX*NUM_THREADS-raceCount );
    }   // end RaceCondition constructor



    class RaceThread extends Thread {
    public void run() {
        for ( int i=0; i<MAX; i++){
        try {
            update( i );        
        }    // These  catches show when one thread steps on another's values
        catch( ArrayIndexOutOfBoundsException ai ){ System.out.print("A"); }
        catch( OutOfMemoryError oome ) { System.out.print("O"); }
        }
    }

    // so we don't lose counts, need to synchronize on some object, not primitive
    // Created "countLock" to show how this can work.
    // Comment out the synchronized and ending {, see that we lose counts.

//    public synchronized void update(int i){   // use A
    public void update(int i){                  // remove this when adding A
//      synchronized(countLock){            // or B
//      synchronized(this){             // or C
        raceCount = raceCount + 1;
        raceList.add( i );      // use Vector  
//          }           // end block for B or C
    }   // end update

    }   // end RaceThread inner class


} // end RaceCondition outter class
Urissa answered 13/4, 2013 at 16:29 Comment(1)
Synchronizing with '(this)' does work, and does not 'use the current thread as the synchronizing object', unless the current object is of a class that extends Thread. -1Eliath

© 2022 - 2024 — McMap. All rights reserved.