vineri, 8 iulie 2011

Synchronization good, synchronized methods bad

I've been preoccupied lately with the problem of synchronization.

Synchronization in java relies on a cool concept of acquiring a lock, then performing some action, all of this, of course, in the context of multiple threads working with the same data.
It took me a while to get what "the lock" was, so I'll just sum it up in code:

int myCoolNumber = 0;
Object myCoolLock =new Object();

A lock is merely a concept, not really some obscure class in some magical package. It's only role is to exist, thus a java.lang.Object will suffice.

Now, suppose that what you want to do is to increment the value of myCoolNumber. If you're not familiar with threads, I'll be the one to bring the bad news: you can't just increment a variable like myCoolNumber++, because you will lose counts.
A good analogy to explain why, without going into details is this: if you've got multiple people working on a project, if they are not aware of that their colleagues are working on, they might do the same thing. This is especially bad when it's crucial to know what the others did (like how many times the myCoolNumber was incremented.

So what you do is this:

synchronized ( myCoolLock){
myCoolNumber++
}

This is called a synchronized block. That's everything you need to ensure you will never lose counts, if some method in some thread wants to increment myCoolNumber.
This approach makes sure that no other threads can increment myCoolNumber at the same time (no data-races)


Now why synchronized blocks are a good thing whereas synchronized methods are bad?

We have this:

class foo{
int myCoolNumber=0;
public synchronized void incrementAndMore(){
myCoolNumber++;
//some other code;
}
}

A synchronized method uses the same mechanism as the synchronized block, BUT whereas for the synchronized block you have control over the lock of a specific field, the intrinsic lock of a synchronized method is the "this" reference.

Now it's obvious that by acquiring the intrinsic lock of the object itself, you block access to that object while the method executes. In other words, the price payed for making sure the myCoolNumber field is thread safe is giving up the advantages of parallel processing in the first place.
This can be all good and toasty if you don't really have more than 1 field for which thread safety is an issue, but when you have to deal with multiple fields, synchronized blocks might be the better option.

Niciun comentariu:

Trimiteți un comentariu