开发者

Java: when to syncrhonize methods and blocks

开发者 https://www.devze.com 2023-04-13 07:07 出处:网络
I understand that the synchronized keyword is used to prevent multiple threads from accessing the same chunk of code (either a whole method or a block of synched code within a method) at the same time

I understand that the synchronized keyword is used to prevent multiple threads from accessing the same chunk of code (either a whole method or a block of synched code within a method) at the same time, and that this helps prevent nasty things from occurring, such as deadlocks.

What I'm stumped on is when it is appropriate to use this mechanism: what rule of thumb(s) exist as to when a certain fragment of code should be thread-safe? The only instance I can think of is when the order of events for something happening are critical, but even then I can't think of an actual, concrete, real-world example.

I've never written a 开发者_开发百科synchronized method or block, and so "seeing the forest through the trees" is difficult for me, somehow. Any contextual examples are greatly appreciated! Thanks in advance.


Use synchronized when two or more threads need to modify the same resource, and you want to enforce that only one of them gets access to the resource at any given time. For example, when you have a set of variables that should be modified together.

Here's an example from the Java tutorial:

  • http://download.oracle.com/javase/tutorial/essential/concurrency/syncrgb.html

The whole section is quite enlightening:

  • http://download.oracle.com/javase/tutorial/essential/concurrency/sync.html


Use synchronized when multiple threads acting on the same set of data and if you want what one thread is doing is visible by other thread before the second thread start acting on the data.

you want to use the synchronized keyword when

a) if you want the data to be operated on only by one thread at a time ( mutex)

b) if you want all the changes done by previous thread to be visible to the other thread when it comes in .

c) when you want the entire operation done by the thread to be atomic ( i.e completely finished instead of leaving in the middle) .

You can use synchronized methods or block to resolve all these above conditions.

The major use cases in the real world is like customer producer pattern -- like one thread fetching the data, another set of threads validating and updating the data and another thread persists the data.

I found it very useful in in memory databases and real time operations where milliseconds are critical.


When to use synchronized: never. History has shown that it's near enough impossible to get it right in a non-trivial application, thus the rise in popularity of libraries and languages that provide alternate solutions to concurrency: actor frameworks, software transactional memory, and the like.


Producer-consumer is a classic context where synchronization is highly needed if correct results are required. A producer is a code component ( a class in Java ) that produces some units and a Consumer is another component that consumes these units produced. The producers and consumers must work independent of each other , yet must produce meaningful behaviour.

In general , anywhere multiple threads process some state of an object independently , but need to produce results meaningful only when they are coordinated - you will need to use the synchronized semantics.


While most of the discussion has focused on the synchronization I didn't think they really discussed the difference. So let's look at how block and method synchronization are the same.

public synchronized method( Param param ) {
   // do some work in here
}

public method( Param param ) {
    synchronized( this ) {
        // do some work here
    }
}

These two methods are the exact same. Notice there is no code above or below the synchronized block. If they were the some code outside the block that code would be executed by multi-threads. Another distinction between them is that you can alter between code that runs without locking and code that runs under locking. This can be used to boost performance if only a small portion needs to run under locking, and the meat of the method can run multi-threaded boosting performance if that portion is a hotspot. Now let's see how blocks can offer more granularity of synchronization than methods.

public synchronized method1( Param param ) {
    // do something unrelated to method 2
}

public synchronized method2( Param param ) {
   // do something unrelated to method 1
}

In this case method1 AND method2 would only allow a thread at once in either of them at a time because synchronized methods lock on this. Of course if we synchronized on this in a block it would be the same. However, we don't have to synchronize on this always. Here is a way to make method1 and method2 locking independent.

Object method1Lock = new Object();
Object method2Lock = new Object();

public method1( Param param ) {
   synchronized( method1Lock ) {
      // do stuff
   }
}

public method2( Param param ) {
   synchronized( method2Lock ) {
      // do stuff
   }
}

This is important distinction because now method1 and method2 can be executed simultaneously where using synchronized methods will not allow this. You have to keep in mind that method1 and method2 MUST be independent in their code. If method1 modifies an instance variable, and method2 reads that variable they aren't independent, and you must use method synchronization. However, if method1 accesses separate instance variables than method2 then this technique can be used. What does that all mean? Neither technique is superior to the other. Method synchronization is simple and straight forward, but might have lower performance because it locks too much. Block synchronization fixes that problem, but its more complex.

Synchronization is important. There are problems that can't be done with out it. However, it's best to be careful, and try very hard to not use it when you don't have to. There are some great techniques that eliminate locking, and can improve throughput so you have to know when to use those as well. This all just takes experience and wisdom. Good luck.


Use synchronize methods if:

(a) you want to add the complete code of the method as thread-safe (in plain simple terms this code going to be executed by one thread max at a time)
(b) You dont want to use different lock for different method. Adding synchronization to non-static method takes the instance-object lock. While adding the synchronized to multiple methods, all will have same lock, which means any code of all synchronized method is going to be executed by one thread max at a time

Use synchronize block if:

(a) you only want a portion of code inside method to be thread-safe.
(b) You want flexibility to choose your own lock (every object contains monitor lock).

All portion of code comes under one synchronized lock (method or block whatever) can be executed by only thread at a go. Rest other will lined up waiting for the monitor lock.

A beautiful way to use synchronization block is shown at my blog here:

http://singletonjava.blogspot.com

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号