I make multiple web requests from an Android application I'm working on. I want all these requests to be processed one at a time in the order they arrive, does my below code do that?
The way I read and understand synchronized is that of all the threads I spin off, only one can be in any of the below methods at one time. For example, if a user tries to postPhoto in one thread and then immediately getData in another thread, the getData thread will have to wait until the postPhoto thread is finished before it starts getting data. Since all my web requests go through this class and all the methods are synchronized, that means they're essentially queued up correct?
public class Controller {
public synchronized static String getData(String url, String limit) { ... }
public synchronized static String postPhoto(String filepath, int server_id) { ... }
public synchronized static InputStream getPhoto(String thumbnailPath) { ... }
public synchronized static String createIncident(String name, String description) { ... }
public synchronized static String updatePerson() { ... }
synchronized static boolean verifyConnection(String response) { ... }
}
EDIT:
I probably should have mentioned that even though some of the above methods are called createIncident or updatePerson, all of them ONLY make httprequests, the code inside all of the methods is generally the same except for important minor variations. In other parts of my code, I spin off threads to call these methods, and that's the part I was asking about. Since those threads call these methods, thread B that is calling getData will have to wait until thread A finishes it's part of postPhoto.
It depends on your implementation as well.
Is your controller singleton or instance per thread?
do your methods use shared objects?
If singleton and methods sharing objects, then there is no guarantee for thread1 to run postPhoto and then immediately after that getData even if you call sequentially. Another thread may take the turn and start running in between thread1 calling those 2 methods.
Bear in mind, synchronized keyword locks on the class itself so at any time there will be only one method executing. No 2 synchronized methods will be run at the same time.
Yes, you are right. The combination of synchronized and static guarantees what you want.
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.
Thread A does:
class A{
public String value;
public void methodA(String value){ //lets say value="test"
this.value=value;
//some code
// Thread B interrupts
System.out.println(value); // prints "haha" but I want it to be "test"
}
}
Thread B does:
class B{
public void methodB(){
a.setValue("haha");
}
}
methodB and methodA are some kinds of listener methods, which are executed in separate Threads.
How can I make sure that value does not change, as long as methodA has not finished? But I want also that "haha" is assigned to value afterwards. So I want B to wait till A has finished methodA and then assign "haha" to value.
The easiest way is to use 'synchronized' keyword on method that change the value of a field.
For example we have class that stores the data:
public class Data {
String value = "";
public synchronized void setValue(String val) {
this.value = val;
System.out.println(val);
}
}
And then Threads only use this method to update the value. Only one thread at the time can execute this method (no interrupts).
If you want to propagate this on two methods (like I suppose is the case). You can use two options. Or use synchronized on both methods or use external lock object.
If you want to be sure, that for example thread A has to be first to execute, you can use CountDownLatch object, which will stop other threads until thread A won't decrement the latch.
There are many ways to handle synchronization. You should be more precise to what you want to achieve and what kind of scenario you want to handle. Like for example - Is a.setValue("haha") a method from class A?
I would also recommend to look at documentation about concurrency https://docs.oracle.com/javase/tutorial/essential/concurrency/ .
If you just want methodA() to complete before methodB() is called, then you should call both methods from the same thread. In general, if you want your program to do certain things in a certain order, the best way to accomplish it is
to do all of the things in a single thread.
On the other hand, you might want both threads to work in parallel most of the time, but there might be one particular point that you don't want thread B to pass until thread A gets there. The Java standard library provides a variety of different synchronization objects that you could use. E.g., java.util.concurrent.CountDownLatch.
Initialization:
CountDownLatch countDownLatch=new CountDownLatch(1);
threadA.start();
threadB.start();
Thread A:
doSomeStuff();
methodA();
countDownLatch.countDown();
doSomeMoreStuff();
ThreadB:
doSomeOtherStuff();
countDownLatch.await();
methodB();
doSomeMoreOtherStuff();
The doSomeStuff() and doSomeOtherStuff() calls could happen concurrently, and the doSomeMoreStuff() and doSomeMoreOtherStuff() calls could happen concurrently, but the methodA() and methodB() would be serialized in this case.
In Java Concurrency In Practice, the author stated that
Immutable objects can be published through any mechanism
Immutable objects can be used safely by any thread without additional synchronization, even when synchronization is not used to publish them.
Does it mean that the following idioms are safe to publish immutable objects?
public static List<ImmutableObject> list = new ArrayList<ImmutableObject>();
// thread A invokes this method first
public static void methodA () {
list.add(new ImmutableObject());
}
// thread B invokes this method later
public static ImmutableObject methodB () {
return list.get(0);
}
Would there be any data race?
(which means thread B may not be able to see the Immutable Object in the list added by thread A)
Thank you very much.
More, the author said that the following code is safe if Resource is immutable.
#NotThreadSafe
public class UnsafeLazyInitialization {
private static Resource resource;
public static Resource getInstance() {
if (resource == null)
resource = new Resource(); // unsafe publication
return resource;
}
}
Section16.3
The guarantee of initialization safety allows properly constructed immutable objects to be safely shared across threads without synchronization, regardless of how they are published even if published using a data race. (This means that unsafeLazyInitialization is actually safe if Resource is immutable.)
For the 2nd part of this question, it is discussed in detail in another question (click here)
Yes, you are correct, there is a data race.
Only the ImmutableObject is immutable and can be shared safely between threads, your List, however, does not have these same guarantees, so there is a data race between adding the ImmutableObject and retrieving it.
In JCIP, the authors meant immutable objects are safe to publish in the sense that you don't have to worry about doing things like making defensive copies.
As to:
Immutable objects can be used safely by any thread without additional
synchronization, even when synchronization is not used to publish
them.
This statement means that given 2 threads with an immutable object A that they both acquired through any means, they can both use object A without worrying about thread-safety issues.
Your List<ImmutableObject> list container object is not immutable. Hence, add and get method on it will not be threadsafe. These methods need to be synchronized for concurrent access from multiple threads.
Your question suggests that you are anticipating section 5.3 - blocking queues and the producer consumer pattern. Here is something similar using a blocking queue:
public class Blocking
{
private BlockingQueue<ImmutableObject> queue = new ArrayBlockingQueue<ImmutableObject>(10);
public void methodA() {
queue.add(new ImmutableObject());
}
public ImmutableObject methodB() throws InterruptedException
{
return queue.take();
}
static class ImmutableObject
{
}
}
The blocking queue is highly mutable - but is designed to be thread safe so you can use it without extra synchronization. As long as the objects that you are passing are immutable the entire design is thread safe.
In the example above, methodB uses "take" which will block until methodA is called to put something in the queue. Or until the thread is interrupted at which point it would exit via an InteruptedException
Yes there is definite chance of data race. Here is a situation:
Although Thread A is inside methodA and then Thread B would be executing methodB, there is no guarantee that methodA has returned before methodB. If, unfortunately, methodB has already returned while methodA is yet to return, there would be high chance to get IndexOutOfBoundsException:
// thread A invokes this method first
public static void methodA () {
//assume control is taking time at this point, while thread B already returned!!!
list.add(new ImmutableObject());
}
// thread B invokes this method later
public static ImmutableObject methodB () {
return list.get(0);
}
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.