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.
Related
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
public class ThreadTest implements Runnable {
private int counter;
private Date mydate = new Date();
public void upCounter1() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("1 " + counter);
}
}
}
public void upCounter2() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("2 " + counter);
}
}
}
public void upCounter3() {
synchronized (mydate ) {
for (int i = 0; i < 5; i++) {
counter++;
System.out.println("3 " + counter);
}
}
}
#Override
public void run() {
upCounter1();
upCounter2();
upCounter3();
}
public static void main(String[] args) {
Threadtest mtt = new Threadtest();
Thread t1 = new Thread(mtt);
Thread t2 = new Thread(mtt);
Thread t3 = new Thread(mtt);
t1.start();
t2.start();
t3.start();
}
}
I tried this code with various synchronisation techniques and I'd like to make sure I get what's happening. I've read a bunch of articles on this, but none of them broke it down enough for me.
So here's what I observed:
synchronised (this): This works only, if I give the SAME instance of Threadtest to all threads, because if I give each thread its own instance, each will get that instance's intrinsic lock and can access the methods without interruption from the other threads.
However, if I give each thread its own instance, I can do: synchronised (getClass()), because then I get the instrinsic lock of the class
Alternatively, I could do: synchronised (mydate), where the same rules apply that apply to synchronised (this). But it has the advantage of not being public. > I dont really understand this. What is the "danger" of using this?
Alternatively to synchronised (getClass()), I could also use a private static field.
However, I cannot do synchronised(Date.class).
I could synchronise the entire methods (same effecte as with synchronised-block)
making counter volatile doesn't work, because incrementing isn't a truly atomic operation
If I want to make each method accessible individually, I would make three private fields and use them in the synchronised-blocks. I then am effectively using the intrinsic locks of those fields and not of my class or instance.
I also noted that when I use the class-lock, each method is viewed as separate and I have effectively 3 ounters that go to 15. If I use the instance lock, the counter goes to 45. Is that the correct and expected behaviour?
Are my explanations and observations correct? (I basically want to make sure I draw the correct conclusions form the console output I got)
a-c; e-f are correct.
c) Alternatively, I could do: synchronised (mydate), where the same rules apply that apply to synchronised (this). But it has the advantage of not being public. > I dont really understand this. What is the "danger" of using this?
The argument is that other code may also decide to use that object as a lock. Which could cause conflict; when you know that this can never be the case then it is not such an evil thing. It is also usually more of a problem when one uses wait/notify in their code.
d) Alternatively to synchronised (getClass()), I could also use a private static field. However, I cannot do synchronised(Date.class).
You can use Date.class, it would just be a bit weird and falls into the argument discussed in c above about not polluting other classes work spaces.
g) If I want to make each method accessible individually, I would make three private fields and use them in the synchronised-blocks. I then am effectively using the intrinsic locks of those fields and not of my class or instance.
Given that the three methods share the same state, then no, this would not be wise as it would lead to races between the threads.
h) I also noted that when I use the class-lock, each method is viewed as separate and I have effectively 3 counters that go to 15. If I use the instance lock, the counter goes to 45. Is that the correct and expected behaviour?
No, this sounds wrong but I may have misunderstood you. I would expect the total to be 45 in both cases when using either this or this.getClass() as the lock.
Your code is threadsafe as it stands, if slow (you are writing to the console while holding a lock) - but better correct and slow than wrong and fast!
a) synchronised (this): This works only, if I give the SAME instance of Threadtest to all threads, because if I give each thread its own instance, each will get that instance's intrinsic lock and can access the methods without interruption from the other threads.
Your code is threadsafe either case - that is, it will give the exact same results every time. If you pass the same instance to three different threads the final line of output will be "3 45" (since there is only one counter variable) and if you give each thread its own instance there will be three lines reading "3 15". It sounds to me like you understand this.
b) However, if I give each thread its own instance, I can do: synchronised (getClass()), because then I get the instrinsic lock of the class
If you do this your code is still threadsafe, but you will get three lines reading "3 15" as above. Be aware that you will also be more prone to liveness and deadlock issues for the reason stated below.
c) Alternatively, I could do: synchronised (mydate), where the same rules apply that apply to synchronised (this). But it has the advantage of not being public. I dont really understand this. What is the "danger" of using this?
You should try to use private locks where you can. If you use a globally-visible object (e.g. this or getClass or a field with visibility other than private or an interned String or an object that you got from a factory) then you open up the possibility that some other code will also try to lock on the object that you are locking on. You may end up waiting longer than you expect to acquire the lock (liveness issue) or even in a deadlock situation.
For a detailed analysis of things that can go wrong, see the secure coding guidelines for Java - but note that this is not just a security issue.
d) Alternatively to synchronised (getClass()), I could also use a private static field. However, I cannot do synchronised(Date.class).
A private static field is preferable to either getClass() or Date.class for the reasons stated above.
e) I could synchronise the entire methods (same effecte as with synchronised-block)
Pretty much (there are currently some insignificant byte code differences), but again you should prefer private locks.
f) making counter volatile doesn't work, because incrementing isn't a truly atomic operation
Yes, you may run into a race condition and your code is no longer threadsafe (although you don't have the visibility issue mentioned below)
g) If I want to make each method accessible individually, I would make three private fields and use them in the synchronised-blocks. I then am effectively using the intrinsic locks of those fields and not of my class or instance.
You should not do this, you should always use the same lock to access a variable. As well as the fact that you could have multiple threads reading/writing to the same variable at the same time giving race condition you also have a subtler issue to do with inter-thread visibility. The Java Memory Model guarantees that writes done by one thread before a lock is released will be seen another thread when that other thread acquires the same lock. So thread 2 executing upCounter2 may or may not see the results of thread 1 executing upCounter1.
Rather than thinking of "which blocks of code do I need to execute?" you should think "which pieces of state do I need to access?".
h) I also noted that when I use the class-lock, each method is viewed as separate and I have effectively 3 ounters that go to 15. If I use the instance lock, the counter goes to 45. Is that the correct and expected behaviour?
Yes, but it has nothing to do with the object you are using for synchronisation, rather it's because you have created three different ThreadTest objects and hence have three different counters, as I explained in my answer to your first question.
Make sure that you understand the difference between three threads operating on one object and one thread operating on three different objects. Then you will be able to understand the behaviour you are observing with three threads operating on three different objects.
a) Correct
b) Correct
c) There could be some other bunch of code using your this or class in another part of your application where your class is accessible. This will mean that unrelated code will be waiting for each other to complete.
d) You cannot do synchronisation on Date.class because of the same reason above. There may be unrelated threaded methods waiting for each other unnecessarily.
e) Method synchronisation is same as class lock
g) Correct
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.
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;
}
}
}
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.