views:

301

answers:

10

From Sun's tutorial:

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed) This strategy is effective, but can present problems with liveness, as we'll see later in this lesson.

Q1. Is the above statements mean that if an object of a class is going to be shared among multiple threads, then all instance methods of that class (except getters of final fields) should be made synchronized, since instance methods process instance variables?

A: 

Yes, that's correct. All methods that modify data or access data that may be modified by a different thread need to be synchronized on the same monitor.

The easy way is to mark the methods as synchronized. If these are long-running methods, you may want to only synchronize that parts that the the reading/writing. In this case you would definie the monitor, along with wait() and notify().

Milan Ramaiya
can u provide an example which uses wait() and notify() along with synchronized statements?
Yatendra Goel
A: 

The simple answer is yes. If an object of the class is going to be shared by multiple threads, you need to syncronize the getters and setters to prevent data inconsistency. If all the threads would have seperate copy of object, then there is no need to syncronize the methods. If your instance methods are more than mere set and get, you must analyze the threat of threads waiting for a long running getter/setter to finish.

ring bearer
apart from setters and getters, other instance methods also process that shareable data. So should I synchronized all those instance methods that access/writes that shareable data?
Yatendra Goel
+3  A: 

No. It means that synchronized methods are a way to achieve thread safety, but they're not the only way and, by themselves, they don't guarantee complete safety in all situations.

Steve Emmerson
Could be please tell me three things. First, what are those other ways which can be used for thread safety (I think volatile variables are one out of them). Second, in what situations the synchronization approach fails? Third, what problems you think that we encounter with synchronization?
Yatendra Goel
Another way for thread safety is immutability. Note that your object could be considered immutable if it meet following conditions:1. All its primitives are final2. All its non-primitives are immutable.Also it's important to understand that its not that easy to achieve true thread safety. There is a condifional thread safety when each individual operation may be thread-safe, but certain sequences of operations may require external synchronization. Typical example is Hashtable. You find more on this topic here: http://www.ibm.com/developerworks/java/library/j-jtp09263.html
wax
@Goel: 1) volatile variables, thread and stack confinement, the java.util.concurrent package, etc.; 2) deadlock; 3) the only "problem", per se, is Amdahl's law. I also recommend Goetz's book "Java Concurrency in Practice".
Steve Emmerson
+2  A: 

Not necessarily. You can synchronize (e.g. place a lock on dedicated object) part of the method where you access object's variables, for example. In other cases, you may delegate job to some inner object(s) which already handles synchronization issues.
There are lots of choices, it all depends on the algorithm you're implementing. Although, 'synchronized' keywords is usually the simplest one.

edit
There is no comprehensive tutorial on that, each situation is unique. Learning it is like learning a foreign language: never ends :)

But there are certainly helpful resources. In particular, there is a series of interesting articles on Heinz Kabutz's website.
http://www.javaspecialists.eu/archive/Issue152.html (see the full list on the page)

If other people have any links I'd be interested to see also. I find the whole topic to be quite confusing (and, probably, most difficult part of core java), especially since new concurrency mechanisms were introduced in java 5.

Have fun!

Nikita Rybak
can you provide me some links of tutorials on that?
Yatendra Goel
edited answer to allow better formatting, like linebrakes :/
Nikita Rybak
+1 for the link. It really helped me.
Yatendra Goel
+1  A: 

In the most general form yes.

Immutable objects need not be synchronized.

Also, you can use individual monitors/locks for the mutable instance variables (or groups there of) which will help with liveliness. As well as only synchronize the portions where data is changed, rather than the entire method.

Tim Bender
A: 

You could use synchronized methods, synchronized blocks, concurrency tools such as Semaphore or if you really want to get down and dirty you could use Atomic References. Other options include declaring member variables as volatile and using classes like AtomicInteger instead of Integer.

It all depends on the situation, but there are a wide range of concurrency tools available - these are just some of them.

Synchronization can result in hold-wait deadlock where two threads each have the lock of an object, and are trying to acquire the lock of the other thread's object.

Synchronization must also be global for a class, and an easy mistake to make is to forget to synchronize a method. When a thread holds the lock for an object, other threads can still access non synchronized methods of that object.

Finbarr
A: 

synchronized methodName vs synchronized( object )

That's correct, and is one alternative. I think it would be more efficient to synchronize access to that object only instead synchronize all it's methods.

While the difference may be subtle, it would be useful if you use that same object in a single thread

ie ( using synchronized keyword on the method )

class SomeClass {
    private int clickCount  = 0;

    public synchronized void click(){
        clickCount++;
    }
 }

When a class is defined like this, only one thread at a time may invoke the click method.

What happens if this method is invoked too frequently in a single threaded app? You'll spend some extra time checking if that thread can get the object lock when it is not needed.

class Main {
    public static void main( String  [] args ) {
         SomeClass someObject = new SomeClass();
         for( int i = 0 ; i < Integer.MAX_VALUE ; i++ ) {
             someObject.click();
         }
    }
 }

In this case, the check to see if the thread can lock the object will be invoked unnecessarily Integer.MAX_VALUE ( 2 147 483 647 ) times.

So removing the synchronized keyword in this situation will run much faster.

So, how would you do that in a multithread application?

You just synchronize the object:

synchronized ( someObject ) {
    someObject.click();
}

Vector vs ArrayList

As an additional note, this usage ( syncrhonized methodName vs. syncrhonized( object ) ) is, by the way, one of the reasons why java.util.Vector is now replaced by java.util.ArrayList. Many of the Vector methods are synchronized.

Most of the times a list is used in a single threaded app or piece of code ( ie code inside jsp/servlets is executed in a single thread ), and the extra synchronization of Vector doesn't help to performance.

Same goes for Hashtable being replaced by HashMap

OscarRyz
Note that you would also need to synchronize the creation of the `someObject` variable, or have it created by the main thread.
Finbarr
@finbarr In multi-threaded app, the `someObject` must be created by the main thread. If not, then I think that it won't be shared among the threads started from main thread and if it is not shareable that there is no need to synchronize the creation of it.
Yatendra Goel
@Oscar You have indicated a good point but an application can be a single-threaded app or a multi-threaded app. So if I am coding a single-threaded app, then why would I need to synchronize anything at all. And if I am coding a multi-threaded app, then why I shouldn't go with the synchronization of the whole instance methods or the part of those instance methods, instead of synchronizing the `someObject.click()` at every place.
Yatendra Goel
@Yatendra: Because you may need a piece of code that runs on both. If you are sure on which scenario your code will be used, then, it is correct to go with one approach or the other. But if your code is to be reused in unknown scenarios, then you should pick wisely because you won't be able to change afterward ( *see: How to desing a good API and why it matters : http://www.youtube.com/watch?v=aAb7hSCtvGw on YouTube* ) But again this is just another alternative, that's why I started my answer as: *"...That's correct, and is one alternative. I think it would..."* :)
OscarRyz
+3  A: 

In order to understand concurrency in Java, I recommend the invaluable Java Concurrency in Practice.

In response to your specific question, although synchronizing all methods is a quick-and-dirty way to accomplish thread safety, it does not scale well at all. Consider the much maligned Vector class. Every method is synchronized, and it works terribly, because iteration is still not thread safe.

Yishai
+1  A: 

In fact getters a should be synchronized too or fields are to be made volatile. That is because when you get some value, you're probably interested in a most recent version of the value. You see, synchronized block semantics provides not only atomicity of execution (e.g. it guarantees that only one thread executes this block at one time), but also a visibility. It means that when thread enters synchronized block it invalidates its local cache and when it goes out it dumps any variables that have been modified back to main memory. volatile variables has the same visibility semantics.

wax
+1  A: 

No. Even getters have to be synchronized, except when they access only final fields. The reason is, that, for example, when accessing a long value, there is a tiny change that another thread currently writes it, and you read it while just the first 4 bytes have been written while the other 4 bytes remain the old value.

Daniel
... but getters of final fields don't, since their values will never change.
paulcm
Sorry, I read getters "and" final fields in the description. You are right.
Daniel