Reputation: 163
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 Object
s including primitive types like int
,float
etc.
e.g.
int a=1;
synchronized(a){}//why is this forbidden
Upvotes: 3
Views: 4338
Reputation: 5203
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 long
s and double
s, 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
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
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 Java
works 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
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
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
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