PTech
PTech

Reputation: 163

Why is the synchronize keyword restricted to non primitive fields only?

In java there is a synchronize keyword that is used to avoid multiple thread access to a method or some block of code at some point.

My question is why can’t the synchronize keyword be used with primitive variables? I know that java does not permit this. But what is the logic as to why this isn’t permitted since all variables in java are Objects including primitive types like int,float etc.

e.g.

int a=1;
synchronized(a){}//why is this forbidden 

Upvotes: 3

Views: 4338

Answers (6)

The simple (and real) reason is that locks need additional storage space and the primitive types don't have 'room' for these lock bits, as they are just what they are, unboxed types. The boxed versions of these like java.lang.Integer etc. do have room for the locks, and so they have them. Note that you can put a primitive type directly on the (JVM) stack, but you can only put a reference there to a boxed type.

One might also recall here that most primitive accesses (meaning reads and writes) are guaranteed atomic in Java up to '32-bit', so except for longs and doubles, access to which may be implemented as two operations, so are not guaranteed atomic. Except (also) that due the somewhat complicated Java Memory Model even though 32-bit writes are atomic (so you can't see inconsistent half words on these), updates may not immediately propagate to other threads! OTOH, as soon as you make some primitive type volatile it is guaranteed that other threads will see the change "as soon as possible" and it will also be (inter-thread) atomic even for the 64-bit quantities. So, as far as just reads and writes are concerned (set and get) java.util.concurrent.AtomicLong merely declares a volatile long (and uses no synchronized around its set and get).

One answer (already) mentioned java.util.concurrent, but that is not merely to give atomic reads and writes e.g. of Booleans, but to also give more complex atomic ops (on those) like compareAndSet. But for 64-bit types java.util.concurrent also provides atomic reads and writes, albeit in a simple volatile fashion.

Upvotes: 0

ursa
ursa

Reputation: 4601

Restriction to use reference-typed objects as synchronized(..) argument comes from the idea of encapsulation, when you and only you control who and how can access your lock (ref or value).

Imagine the case when you want to take a lock on value-typed (primitive) lock int x = 5, then inside synchronized block another lock on int y = 0. In the same time other part of your project (or 3-rd party library) also takes these locks in opposite order - first int a = 0, then int b = 5.

Result? Deadlock. Why? Because of lack of encapsulation - you can't control visibility of value-typed (primitive) variables. They always are public, by nature.

Upvotes: 0

senseiwu
senseiwu

Reputation: 5279

I suppose by variable, you meant class fields. But this is not how synchronization works in Java.

The aim of synchronized block or method is to prevent multiple threads changing the state of a class variable at the same time. Synchronization in Javaworks by owning a lock - if you have synchronized method, you are using an intrinsic lock of the object, otherwise you have to supply a lock. If fields were to be declared as synchronized, that would more or less force all the methods in that class that uses the field to work in a synchronized way by owning the lock and this would be bad for performance.

If you are looking for synchronization guarantees at field level without having to synchronize methods, consider using Atomic variables like java.util.concurrent.atomic.AtomicInteger

Upvotes: 1

user3276247
user3276247

Reputation: 1084

Variable in itself does not stand on its own. It needs a class to have some context. That's why the lock is on the class or the object and not on the variable.

Upvotes: 1

Niraj Patel
Niraj Patel

Reputation: 2208

you mean to say you need to synchronize operations on variable ? like you want to protect operation on variable e.g. increment,decrement ? java has atomic API like java.util.concurrent.AtomicBoolean etc..

Benefits of using Atomic Concurrency classes is that we don’t need to worry about synchronization at each and every place we are dealing with integers and it’s assumed to be more efficient that synchronization which involves locking resources.

Upvotes: 0

Dávid Szabó
Dávid Szabó

Reputation: 2247

You can synchronize a variable too.

synchronized(myvariable) {
.......
}

Also you should check the 'volatile' keyword. http://en.wikipedia.org/wiki/Volatile_variable#In_Java

Upvotes: 0

Related Questions