I'm kind of confused about how to implement synchronized blocks in Java.
Here is an example situation:
public class SlotWheel extends Thread implements ActionListener
{
private int currentTick; // This instance variable is modified in two places
private synchronized void resetCurrentTicks()
{
currentTick = 0;
}
private synchronized void incrementCurrentTicks()
{
++currentTick;
}
public void actionPerformed(ActionEvent e)
{
resetCurrentTicks();
}
}
While the program is running, it's possible that a user clicks a button which invokes actionPerformed which then calls resetCurrentTicks. At the same time, the running thread is calling incrementCurrentTicks on each loop iteration.
Because I'm still new to Java and programming, I'm not sure if my implementation is protecting currentTick from becoming corrupted.
I have this feeling that my implementation would only work if incrementCurrentTicks were to be called in actionPerformed and in the running thread, but because I'm manipulating currentTick from different methods, my implementation is wrong.
Looks ok.
See http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
It is not possible for two invocations of synchronized methods on the same object to interleave
Of course you should consider whether it is the GUI thread trying to mess with the ticks or not. In your simple case it's probably ok, but in a more complex case you might want to push the "work" out of the GUI thread.
Your instincts are correct. It is difficult to synchronize access to class properties consistently across multiple methods. Rather than attempting to do so, I would recommend you take a look at java.util.concurrent.atomic.AtomicInteger. It provides you with safe, concurrent access to the underlying property without writing and testing alot of boilerplate code.
Incorporating it into your code, you would end up with something like this:
public class SlotWheel extends Thread implements ActionListener {
private AtomicInteger currentTick = new AtomicInteger();
private void resetCurrentTicks() {
currentTick.set(0);
}
private void incrementCurrentTicks() {
currentTick.incrementAndGet();
}
public void actionPerformed(ActionEvent e)
{
resetCurrentTicks();
}
}
First off, Java guarantees that "scalar" values -- integers, chars, floats, etc -- are atomic in themselves in that you cannot simultaneously modify such a value and get a mixture of the two sources. You're guaranteed to get one value or the other of two "simultaneous" modifications. You can, however, get an inconsistent result from, eg, x++, since two threads may attempt to simultaneously increment x and possibly only one increment might occur. (OTOH, two threads simultaneously performing x = 7; will obviously not interfere with each other -- simultaneous access does not cause an explosion or anything.)
Next, understand that the synchronized keyword is used in two slightly different contexts -- as a method modifier and as a block modifier. There is some modest difference between the two.
When used as a block modifier you say synchronized(object_ref) {some block}. In this case the synchronized statement gets a lock on the object identified by object_ref and all other syncronized statements that might simultaneously attempt to execute referencing the same object will be held off while the current statement finishes its block.
When you use it as a method modifier, the function is the same except that, for a non-static method, the "this" object is the one that is locked, and the entire method is is "protected" by the lock.
(For a static method, on the other hand, the Class object is locked -- a slightly special case, equivalent to synchronized(ClassName.class){some block} as a synchronized block.)
It's important to understand that for two synchronized blocks or methods to be prevented from simultaneously executing they must be referencing, as their synchronizing object, the same object, not simply one of the same class.
You are correct, in that it is not safe. However, you can simply synchronize on any Object in scope, and remove "synchronized" from the method definition
public class MyThread {
private Object lock = new Object();
private int counter;
protected void threadMetod() {
synchronized (lock) {
counter++;
}
}
public void otherReset() {
synchronized (lock) {
counter = 0;
}
}
}
Related
Is it just that two synchronised methods that can't run concurrently?
For example, someone codes 2 Java classes.
public class A {
public synchronized void a1(){
//do something }
public void a2(){
//do something }
public synchronized int a3(){
int var = 0;
//do something changing var
return var; } }
public class B {
public void b1(){
//do something
}
public synchronized int b2(){
int var = 0;
//do something changing var
return var;
}
public void b3(){
//do something
}
}
With a main method,
public static void main(String[] args){
A firstA = new A();
A secondA = new A();
B firstB = newB();
//create some threads that perform operations on firstA, secondA and first B and start them
}
Assuming they run in parallel and call methods on the created objects and also assuming that none of these methods are prevented by other mechanisms from running currently.
Out of the methods in the example I gave, are there any that cannot be run concurrently if called at the same time by 2 different threads?
By running concurrently I mean, they will be sequenced so that one will finish before the other starts.
Assuming that there is no other synchronization involved, the only calls that will be mutually excluded are:
firstA.a1() vs firstA.a1()
firstA.a1() vs firstA.a3()
secondA.a1() vs secondA.a1()
secondA.a1() vs secondA.a3()
firstB.b2() vs firstB.b2()
This is because synchronized blocks have to use the same lock for them to have an effect on each other. When you mark a whole method as synchronized, the lock object will be the value of this. So methods in firstA will be completely independent of methods of secondA or firstB, because they use different locks.
The methods in your code that aren't marked synchronized won't even attempt to acquire any lock at all, they can run whenever they want.
Please note that mutual exclusion is just one aspect of multithreading. For your programme to work correctly, you also have to consider things like visibility and safe publication.
Of course, the answer depends on what "something" you "do" when you "do something", and since you don't show that, no one can answer. That's what happens when you omit the significant information. Don't omit the significant information.
What we can say is that the synchronized methods in A do not use the same lock as the synchronized methods in B.
If multiple threads access the same data, then they must synchronize with each other. The only way for threads to synchronize with each other is to use the same means of synchronization. If that's the use of synchronized, then they must synchronize on the same monitor (lock). So if the A methods and B methods access the same data from different threads, and who can tell if they do from what you show? then they won't work as shown.
If any of the unsynchronized methods access the same data from different threads, and the part you didn't show does not have other effective synchronization means, then they won't work.
All this depends on what you decided not to show us.
All of them can run at the same time without inturrupting each other.
because each thread handles different instance, there's no need for them to wait to what so ever synconized method.
I've got a few questions about synchronization in java.
public class A {
private int i;
public A (int t) { i = t; }
public synchronized void increment() {
i++;
}
public synchronized void decrement() {
i--;
}
}
Suppose I have a class implemented as above and I create an object (p) of type A.
I know there can only be one thread executing p.increment(), but is possible for another thread to execute p.decrement() at the same time ?
Thanks~
synchronized does not protect methods. synchronized does not protect objects. synchronized does one thing, and one thing only.
The way you wrote your increment method is actually just a shorthand way of writing this:
public void increment() {
synchronized(this) {
i++;
}
}
This longer way of expressing it make it clear that synchronized is operating on this.
So, the one thing that synchronized does is: The JVM will not allow two threads to be synchronized on the same object at the same time.
If you have an object, p, of type A, then the answer is "no". The JVM will not allow one thread to do the increment at the same time the other thread does the decrement because both threads would be trying to synchronize on the same object, p.
On the other hand, if you have one object p and another object q, both of type A, then one thread could be in a p.increment() call while another thread is in the q.decrement() call. That's because each thread would be synchronized on a different object, and that is allowed.
P.S.: synchronized actually does one other thing that pertains to the Java concept called "Happens Before". That's something you should learn about (Google is your friend) before you get much deeper into multi-threaded programming.
No. Using synchronized as a method modifier is equivalent to wrapping the method with synchronized(this).
No. the synchronized will not allow multiple threads to enter the methods for an instance of the object. Note if you have a p1 AND a p2 of class A you could have p1.increment() running at same time p2.decrement() (etc.) is running.
Actually since the value is wrapped into synchronized methods, it content is also synchronized so no, it won't be executed by another thread.
Note that it can be called by another thread.
Personally, if it is only a matter of decrements/increments, I wouldn't bother synchronizing and would simply use Atomic values.
See documentation
For example I have a class with 2 counters (in multi-threaded environment):
public class MyClass {
private int counter1;
private int counter2;
public synchronized void increment1() {
counter1++;
}
public synchronized void increment2() {
counter2++;
}
}
Theres 2 increment operations not related with each other. But I use same object for lock (this).
It is true that if clients simultaneously calls increment1() and increment2() methods, then increment2 invocation will be blocked until increment1() releases the this monitor?
If it's true, does it mean that I need to provide different monitor locks for each operation (for performance reasons)?
It is true that if clients simultaneously calls increment1() and increment2() methods, then increment2 invocation will be blocked until increment1() releases the this monitor?
If they're called on the same instance, then yes.
If it's true, does it mean that I need to provide different monitor locks for each operation (for performance reasons)?
Only you can know that. We don't know your performance requirements. Is this actually a problem in your real code? Are your real operations long-lasting? Do they occur very frequently? Have you performed any diagnostics to estimate the impact of this? Have you profiled your application to find out how much time is being spent waiting for the monitor at all, let alone when it's unnecessary?
I would actually suggest not synchronizing on this for entirely different reasons. It's already hard enough to reason about threading when you do control everything - but when you don't know everything which can acquire a monitor, you're on a hiding to nothing. When you synchronize on this, it means that any other code which has a reference to your object can also synchronize on the same monitor. For example, a client could use:
synchronized (myClass) {
// Do something entirely different
}
This can lead to deadlocks, performance issues, all kinds of things.
If you use a private final field in your class instead, with an object created just to be a monitor, then you know that the only code acquiring that monitor will be your code.
1) yes it's true that increment1() blocks increment2() and vice versa because they both are implicitly synchronizing on this
2) if you need a better performance consider the lock-free java.util.concurrent.atomic.AtomicInteger class
private AtomicInteger counter1 = new AtomicInteger();
private AtomicInteger counter2 = new AtomicInteger();
public void increment1() {
counter1.getAndIncrement();
}
public void increment2() {
counter2.getAndIncrement();
}
If you synchonize on the method, as what you did here, you lock the whole object, so two thread accessing a different variable from this same object would block each other anyway.
If you want to syncrhonize only a counter at a time so two thread won't block each other while accessing different variables, you have to add the two counters here in two synchronized block, and use different variables as the "lock" of the two blocks.
You are right it will be a performance bottleneck if you use same Object. You can use different lock for individual counter or use java.util.concurrent.atomic.AtomicInteger for concurrent counter.
Like:
public class Counter {
private AtomicInteger count = new AtomicInteger(0);
public void incrementCount() {
count.incrementAndGet();
}
public int getCount() {
return count.get();
}
}
Yes the given code is identical to the following:
public void increment1() {
synchronized(this) {
counter1++;
}
}
public oid increment2() {
synchronized(this) {
counter2++;
}
}
which means that only one method can be executed at the same time. You should either provide different locks (and locking on this is a bad idea to begin with), or some other solution. The second one is the one you actually want here: AtomicInteger
Yes if multiple threads try to call methods on your object they will wait trying to get the lock (although the order of who gets the lock isn't guaranteed.) As with everything there is no reason to optimise until you know this is the bottle neck in you code.
If you need the performance benefits that can be had from being able to call both operations in parallel, then yes, you do not to provide different monitor objects for the different operations.
However, there is something to be said for premature optimization and that you should make sure that you need it before making your program more complex to accommodate it.
One of my textbook mentions that the argument of synchronized() must be this... I know it is wrong. But I heard that since synchronized(this) is safer, one should always use it. Is that true ?
Thank you:)
No it does not have to be always this. Also it simply cannot be in the case of static methods, because there is no this.
Also it is sometimes considered wrong to synchronize to this, because then lock object is visible outside.
public class Example {
private final Object lock = new Object();
// does not compile, there is no 'this' in static context.
public static void staticMethod() {
synchronized (this) {
}
}
public void method() {
int x = 3;
//there is risk that someone else outside our code
//uses same lock
synchronized (this) {
}
//this lock is private
synchronized (lock) {
}
}
}
One of my textbook mentions that the argument of synchronized() must be this... I know it is wrong.
That is incorrect. Either the textbook is incorrect, or you have misunderstood it. The Java language allows you to synchronize on any (non-null) object reference.
But I heard that since synchronized(this) is safer, one should always use it. Is that true?
No that is not true either. It is not safer, and you certainly shouldn't always lock on this.
In fact if you are writing a general purpose library class that needs to lock "itself", it is often a good idea to declare a private lock field; e.g.
private final Object myLock = new Object();
... and lock that object rather than this. This eliminates the kind of problems that can occur is some external code decides to lock the library object for some reason, leading to unwanted contention, and possibly deadlocks between the library classes methods and the external code.
I suspect that the point that the textbook was trying to make is that all methods that are using primitive locks to give mutual exclusion and synchronization on a data structure must use the right object as the lock. This isn't necessarily the data structure object itself, but it does need to signify that object ... in some sense. (If you don't lock the object that signifies the data structure, you risk having one thread not excluding others while it uses / updates the data structure.)
Here is a sketch of the problem that private locks aim to avoid.
/** This class implements thread-safe getting / setting by synchronizing on 'this' */
public class IntHolder {
private int value;
public int getValue() {
synchronized(this) { return value; }
}
public void setValue(int value)
synchronized(this) { this.value = value; }
}
/* Somewhere else, some other code (the "external code") used a holder instance
as the lock for some larger-scale synchronization. */
IntHolder h = ...
synchronized (h) {
/* Do something that takes a long time ... */
}
The problem is that while the external code holds that lock on h, other threads won't be able to read or change the holder's value. If that was intended ... that is fine. However, if the thread-safety of the IntHolder type is intended to be "just an implementation detail" you now a potentially unexpected failure case.
IMO you're better off using 'volatile' and 'synchronized' on fields and methods if you're unsure whether synchronized(this) is a good idea in that particular place.
to put it simply, volatile places an intrinsic mutex on a variable; synchronized places an intrinsic mutex on a function call; synchronized block places an intrinsic mutex around that piece of code locked by the parameter.
Usually you'd make a lock and lock on a Object, but sometimes you want to lock on the instance itself... though, I'd advise caution on locking with a whole class instance if you only need access to one of it's members/fields (something you could've solved using synchronized and volatile in the first place)
The real reason why you might want (or not want) to lock on this is scope of the lock, you can see the lock if you lock on this. if you init a private object, the lock is hidden away.
The argument of synchronized is simply which object the hold will be placed on. It depends on what you want to do in the synchronized block that will determine what the argument should be. Using this puts a hold on the current object.
As a personal anecdote, in the project I'm currently working on, all of my synchronized holds are on COM ports, so that there's no collisions between sending and receiving packets
it doesn't matter which lock you use. Every java.lang.Object can act as a lock. You have to make sure that all operations that work on the same mutable state use the same lock.
so synchronized(this) is exactly as safe as
private final Object lock = new Object();
synchronized(lock)
If you declare a non-static method as synchronized:
public synchronized void doSomething()
{
...
}
then it is synchronized on this. So if your goal is for a synchronized block to be synchronized with synchronized non-static methods like the above, then you do need to use synchronized(this).
But you are correct: you can also write synchronized(someOtherObject), as long as you're aware that that will lock out synchronized methods of someOtherObject rather than of this.
(For static methods, by the way, synchronized synchronizes on the Class instance representing the containing class.)
No , this is not necessary that you should use this .Even you an apply lock on any other object which not an instance of this.
synchronized(obj1){
-------
}
synchronized(obj2){
-------
}
In a single method you can write something like above where you first acquire the lock on some object obj1 and then did work and released and then acquire the lock on obj2.
Aaah, the infamous Avoid synchronized(this) in Java?.
There is, actually, no difference between
public synchronized void doThis() {
}
and
public void doThis() {
synchronized (this) {
}
}
Except on the bytecode level. Both address thread-safety. They both pose a problem as you can potentially introduce deadlock, if (for example, you set a lock of the same class, within its synchronized block).
If you're worried about deadlock, then a dedicated lock should be used, like so:
public class MyClass {
private final Object lock = new Object(); //Must be final
public void doThis() {
synchronized (lock) {
}
}
}
Alternatively, use the Java java.util.concurrent.Lock interface and the java.util.concurrent.locks.ReentrantLock implementation to do basically lock..
I have class with 2 synchronized methods:
class Service {
public synchronized void calc1();
public synchronized void calc2();
}
Both takes considerable time to execute. The question is would execution of these methods blocks each other. I.e. can both methods be executed in parallel in different threads?
No they can't be executed in parallel on the same service - both methods share the same monitor (i.e. this), and so if thread A is executing calc1, thread B won't be able to obtain the monitor and so won't be able to run calc2. (Note that thread B could call either method on a different instance of Service though, as it will be trying to acquire a different, unheld monitor, since the this in question would be different.)
The simplest solution (assuming you want them to run independently) would be to do something like the following using explicit monitors:
class Service {
private final Object calc1Lock = new Object();
private final Object calc2Lock = new Object();
public void calc1() {
synchronized(calc1Lock) {
// ... method body
}
}
public void calc2() {
synchronized(calc2Lock) {
// ... method body
}
}
}
The "locks" in question don't need to have any special abilities other than being Objects, and thus having a specific monitor. If you have more complex requirements that might involve trying to lock and falling back immediately, or querying who holds a lock, you can use the actual Lock objects, but for the basic case these simple Object locks are fine.
Yes, you can execute them in two different threads without messing up your class internals but no they won't run in parallel - only one of them will be executed at each time.
No, they cannot be. In this case you might use a synchronized block instead of synchronizing the whole method. Don't forget to synchronize on different objects.