How would you answer the following question?
A method of a java class contains a block of code that must be
executed atomically. Explain, using appropriate pseudo-code, how you
would ensure that this block of code is executed atomically
Would I achieve this by making the method ..
public final AtomicInteger x = new AtomicInteger(0);
then ensuring the get statement returned:
x.get()
and if I wanted to increment the value of x would I do this?
x.getAndIncrement();
The answer depends on your definition of "atomic"
I know of three valid definitions for atomic:
Atomic as in synchronized: only one thread can be executing the code at one time;
Atomic as in ACID: all of the action/block happens, or none of it does;
Atomic as in uninterruptible: once the block starts, it can't be interrupted, even by task switching.
The first is probably what your professor meant, and it's pretty easy to accomplish (see below).
The second (atomic as in ACID) can be approximated. See below.
The third simply cannot be guaranteed in Java - it doesn't provide access to the "critical sections" primitives required for uninterruptibility. Fortunately, the need for this is pretty much restricted to operating systems and device drivers.
Atomic as in synchronized
This is relatively straightforward: simply enclose your block of code in a synchronized block. I've shown it as a discrete block below, but there are other options:
public void doSomethingQuasiAtomic() {
synchronized (exampleLock) {
// Your code block goes here.
// Only one thread will ever be in this block at a time.
...
}
}
Atomic as in ACID
There's no general-case solution for ACID atomicity, but it can be approximated, also using synchronized code. In order to do this, each of the parts of the action must be safely reversible.
This is how I'd approach it:
For the sake of argument, assume there's a multipart action you need to do on an object we'll call exampleObj, that you have three actions to be performed which can be safely reversed, and that all access to example is synchronized on exampleLock.
synchronized(exampleLock) {
boolean actionOneDone=false;
boolean actionTwoDone=false;
boolean actionThreeDone=false;
try {
actionOneDone=doActionOne(exampleObj); // or perhaps exampleObj.doActionOne();
if(actionOneDone) actionTwoDone=doActionTwo(exampleObj);
if(actionTwoDone) actionThreeDone=doActionThree(exampleObj);
} catch (Exception ex) {
// Whatever seems appropriate here.
} finally {
if (! (actionOneDone && actionTwoDone && actionThreeDone)) {
/* At least one part failed. Back out the completed actions in reverse order.
* Note that we never need to reverse action three since if it completed, so did the others.
*/
if (actionTwoDone) {
reverseActionTwo(exampleObj); // or perhaps exampleObj.reverseActionTwo();
}
if (actionOneDone) {
reverseActionOne(exampleObj);
}
}
}
}
I believe that the expected answer was something like this:
public class A {
public void foo() {
// .. some code
doSomething(); // the critical part
// .. come code
}
public synchronized void doSomething() { // this is a synchronized method
// the critical code
}
}
The execution of doSomething() is not really atomic (Disclaimer: it's very different from atomicity), but the synchronized keyword ensures that only one thread can enter the execution of this method (on one instance of A). I think that is what they meant instead of atomicity.
Here is another question about atomicity in Java. You may find something useful in there.
Related
I have two methods as follows:
class A{
void method1(){
someObj.setSomeAttribute(true);
someOtherObj.callMethod(someObj);
}
void method2(){
someObj.setSomeAttribute(false);
someOtherObj.callMethod(someObj);
}
}
where in another place that attribute is evaluated:
class B{
void callMethod(Foo someObj){
if(someObj.getAttribute()){
//do one thing
} else{
//so another thing
}
}
}
Note that A.method1 and A.method2 are updating the attribute of the same object. If those 2 methods are run in 2 threads, will this work or will there be unexpected results?
Will there be unexpected results? Yes, guaranteed, in that if you modify things you wouldn't want to have an impact on your app (such as the phase of the moon, the current song playing in your winamp, whether your dog is cuddling near the CPU, if it's the 5th tuesday of the month, and other such things), that may have an effect on behaviour. Which you don't want.
What you've described is a so-called violation of the java memory model: The end result is that any java implementation is free to return any of multiple values and nevertheless, that VM is operating properly according to the java specification. Even if it does so seemingly arbitrarily.
As a general rule, each thread gets an unfair coin. Unfair, in that it will try to mess with you: It'll flip correctly every time when you test it out, and then in production, and only when you're giving a demo to that crucial customer, it'll get ya.
Every time it reads to or writes from any field, it will flip this mean coin. On heads, it will use the actual field. On tails, it will use a local copy it made.
That's oversimplifying the model quite a bit, but it's a good start to try to get your head around how this works.
The way out is to force so-called 'comes before' relationships: What java will do, is ensure that what you can observe matches these relationships: If event A is defined as having a comes-before relationship vs. event B, then anything A did will be observed, exactly as is, by B, guaranteed. No more coin flips.
Examples of establishing comes-before relationships involve using volatile, synchronized, and any methods that use these things internally.
NB: Of course. if your setSomeAttribute method, which you did not paste, includes some comes-before-establishing act, then there's no problem here, but as a rule a method called setX will not be doing that.
An example of one that doesn't:
class Example {
private String attr;
public void setAttr(String attr) {
this.attr = attr;
}
}
some examples of ones that do:
Let's say method B.callMethod is executed in the same thread as method1 - then you are guaranteed to at least observe the change method1 made, though it's still a coin flip (whether you actually see what method2 did or not). What would not be possible is seeing the value of that attribute before either method1 or method2 runs, because code running in a single thread has comes-before across the entire run (any line that is executed before another in the same thread has a comes-before relationship).
The set method looks like:
class Example {
private String attr;
private final Object lock = new Object();
public void setAttr(String attr) {
synchronized (lock) {
this.attr = attr;
}
}
public String getAttr() {
synchronized (lock) {
return this.attr;
}
}
}
Now the get and set ops lock on the same object, that's one of the ways to establish comes-before. Which thread got to a lock first is observable behaviour; if method1's set got there before B's get, then you are guaranteed to observe method1's set.
More generally, sharing state between threads is extremely tricky and you should endeavour not do so. The alternatives are:
Initialize all state before starting a thread, then do the job, and only when it is finished, relay all results back. Fork/join does this.
Use a messaging system that has great concurrency fundamentals, such as a database, which has transactions, or message queue libraries.
If you must share state, try to write things in terms of the nice classes in j.u.concurrent.
I assume what you expected is when you call A.method1, someObj.getAttribute() will return true in B.callMethod, when you call A.method2, someObj.getAttribute() will return false in B.callMethod.
Unfortunately,this will not work. Because between the line setSomeAttribute and callMethod,other thread may have change the value of the attribute.
If you are only use the attribute in callMethod,why not just pass the attribute instead of the Foo object. Code as follow:
class A{
void method1(){
someOtherObj.callMethod(true);
}
}
class B{
void callMethod(boolean flag){
if(flag){
//do one thing
} else{
//so another thing
}
}
}
If you must use Foo as the parameter, what you can do is to make setAttribute and callMethod atomic.
The easiest way to achieve it is to make it synchronized.Code as follow:
synchronized void method1(){
someObj.setSomeAttribute(true);
someOtherObj.callMethod(someObj);
}
synchronized void method2(){
someObj.setSomeAttribute(false);
someOtherObj.callMethod(someObj);
}
But this may have bad performance, you can achieve it with some more fine-grained lock.
I'm working on some issue where I have an interface implementation (of GoogleMaps tile provider) in which the method requires its data immediately (not in a callback), but for me to get the data I have to call a method which returns the data in a callback. I have to link these 2 together, and I have something (which I think works, I have yet to test it), but I am worried about some Android Studio warnings I get.
This is the code I've written:
#Override
public Tile getTile(int x, int y, int zoom) {
// If the tile provider is not available, return null
if(tileProvider == null) {
return NO_TILE;
}
// Define the tile request
final TileRequest tileRequest = new TileRequest(tileProvider.getLayer().getTileWidth(), tileProvider.getLayer().getTileHeight());
// Make the call to get the tile data, which, depending on the situation, can possibly
// be handled by another thread.
tileProvider.getTile(x, y, zoom, new GetDataListener<byte[]>() {
#Override
public void onGetData(byte[] data, Exception exception) {
synchronized (tileRequest) {
tileRequest.data = data;
tileRequest.exceptionOccurred = exception != null;
tileRequest.finishedRequest = true;
tileRequest.notify();
}
}
});
synchronized (tileRequest) {
// If, before this statement was reached, the request has already been finished, call and return getTile immediately.
if(tileRequest.finishedRequest) {
return tileRequest.getTile();
} else {
try {
// Wait for the tileRequest to be finished
tileRequest.wait();
// Once it is finished (in the callback a notify is called as soon as its finished, so thats how this code is reached)
// the tile data is available, return the tile
return tileRequest.getTile();
} catch(InterruptedException ex) {
// Exception occurred, return null so GoogleMaps will try it again later
logger.error("Exception in getTile method: {}", ex.getLocalizedMessage());
ex.printStackTrace();
return null;
}
}
}
}
So what Android Studio is giving me, on the second synchronized (tileRequest) { line, is the following warning:
Synchronization on local variable 'tileRequest'
Reports synchronization on a local variable or parameter. Such synchronization has little effect, since different threads usually will have different values for the local variable or parameter. The intent of the code will usually be clearer if synchronization on a field is used.
I am not too confident on my understanding of synchronization, waiting and notifying, so can someone tell me if my approach is valid, regardless of the warning?
EDIT
There were some questions stating that no multiple threads were involved, I updated the comments a bit, but the tileProvider.getTile(...) method gets the tile, but there is no guarantee that this will not happen on another thread.
Synchronizing on a local object may be ignored by the JVM in some situations so you can't count on it having the correct semantics without a detailed analysis. I would suggest a simpler approach:
CountDownLatch done = new CountDownLatch(1);
tileProvider.getTile(x, y, zoom, new GetDataListener<byte[]>() {
#Override
public void onGetData(byte[] data, Exception exception) {
tileRequest.data = data;
tileRequest.exceptionOccurred = exception != null;
tileRequest.finishedRequest = true;
done.countDown();
}
});
done.await();
return tileRequest.getTile();
Note that you probably can't have an if (tileRequest.finishedRequest) return tileRequest.getTile(); before the done.await() because you would lose the visibility guarantee provided by the latch. And based on your code it seems that the latch would be unblocked immediately after finishedRequest is set to true anyway.
Synchronization is required when two threads tries to access and update same resource, and you want only single thread to access the object at any given time.
In your case, tileRequest is a local variable defined in method scope. So each thread will have it's own instance of the object. So synchronizing local variable will just have an overhead of locking the object without any actual multi-threading benefits.
Your code is correct, albeit clunky. Even though you're using a method-local object for synchronization, it's enclosed by GetDataListener, so it'll potentially be shared by different threads.
Take a look at CompletebleFuture. It might make this code more readable.
IMO the compiler warning is over zealous.
Not only that, but it is technically wrong: It is not possible for Java code to synchronize on a variable. Synchronization is something you do to an object.
When you write synchronized (x) { ... }, the x is an expression that is evaluated to yield an object reference. Most programmers expect x to be a private final instance variable or a private final static variable---those are easy cases to understand---but it doesn't have to be that way. x could be a local variable or it could be a method call that returns an object reference.
What's important, is that the object is shared between threads. It doesn't make any sense to synchronize on an object unless some other thread also synchronize on the same object.
The warning message that you're getting is meant to prevent a common newbie mistake. Even if it's technically wrong, it might prevent dozens or hundreds of daily phone calls from confused newbies to some developer help center somewhere.
When I'm working on commercial software, I don't worry as much about whether a decision is "right" or "wrong" as whether it will increase or decrease the number of calls to our support center.
First the code fragments...
final class AddedOrders {
private final Set<Order> orders = Sets.newConcurrentHashSet();
private final Set<String> ignoredItems = Sets.newConcurrentHashSet();
private boolean added = false;
public synchronized void clear() {
added = false;
}
public synchronized void add(Order order) {
added = orders.add(order);
}
public synchronized void remove(Order order) {
if (added) orders.remove(order);
}
public synchronized void ban(String item) {
ignoredItems.add(item);
}
public synchronized boolean has(Order order) {
return orders.contains(order);
}
public synchronized Set<Order> getOrders() {
return orders;
}
public synchronized boolean ignored(String item) {
return ignoredItems.contains(item);
}
}
private final AddedOrders added = new AddedOrders();
...
boolean subscribed;
int i = 10;
synchronized (added) {
while (!(subscribed = client.getSubscribedOrders().containsAll(added.getOrders())) && (i>0)) {
Helper.out("...order not subscribed yet (try: %d)", i);
Thread.sleep(200);
i--;
}
}
What I'd like to know...
Could someone point out which synchronized are not necessary?
Of course this is not the full code but assume that in the full project that all methods are called, and that some combinations of methods are called in the check value first, then modify style
added(the class) is accessed by multipleThreads
client is part of an external Server API, that I'm not entirely sure if it is Thread-Safe yet but I think it must be
ConcurrentHashSet is a google guava Class but it is based on ConcurrentHashMap apparently and the docs say it carries all the same concurrency guarantees.
But I don't really understand completely what those guarantees all are, even though I did some reading. Namely I know it's not ok to just check and set a value in a synchronized HashMap (without synchronizing on the synchronized Map using a synchronized block), however I do not know if you can do that in ConcurrentHashMap or not (without synchronizing on the ConcurrentHashMap using a synchronized block).
The only cases in your code where you really need synchronized are the ones where you test or update the added flag. You need the synchronized block to make sure that changes to the flag are visible across threads, and you also need to make sure that the added flag change is made in step with the change to the orders data structure. The synchronized keyword keeps another thread from barging in and doing something in between checking the flag and changing the data structure (the remove method could be broken like this if you remove the synchronization).
The code toward the end seems problematic because you're locking on the added object and then not letting go of the lock, there's not an opportunity for any other thread to make the changes that the thread is looking for. Although it looks like you're waiting for another object to change, so this criticism may be invalid. Sleeping with a lock held seems dangerous, though. This kind of thing is why Object#wait releases the lock it acquired.
Also note that since you're passing references out to the Orders set, code outside this class can add orders. You should do something to protect this internal data, like returning it wrapped in an immutableSet so callers can't make changes.
In general synchronization is used when you want to impose some granularity on changes, where you have 2 or more changes you want made together, without possibility of interleaving. An example is a check-then-act sequence where you execute some code that makes a change based on the value of something else, and you don't want some other thread to execute in between the check and the action (so the decision to act could be made, then the condition that allowed that action changes, so that the action could be invalid). If individual values are changed but they are unrelated, then you can make them volatile or use Atomic variables, and reduce the amount of locking you have to do.
It's a valid point that the synchronized keyword could be removed in cases like the clear method, where the only thing that changes is the added flag, which could be made volatile. The purpose of the added flag continues to elude me. Anything that enters a value that's already present can turn the flag back to false, it's not apparent that reasoning about any action based on what the current value of the flag makes any sense if this structure is getting modified concurrently.
Without knowing the exact context it's hard to say, but in general, classes created without considering their being used with multiple threads probably need to be reworked extensively before being used in a concurrent environment.
So I've been reading on concurrency and have some questions on the way (guide I followed - though I'm not sure if its the best source):
Processes vs. Threads: Is the difference basically that a process is the program as a whole while a thread can be a (small) part of a program?
I am not exactly sure why there is a interrupted() method and a InterruptedException. Why should the interrupted() method even be used? It just seems to me that Java just adds an extra layer of indirection.
For synchronization (and specifically about the one in that link), how does adding the synchronize keyword even fix the problem? I mean, if Thread A gives back its incremented c and Thread B gives back the decremented c and store it to some other variable, I am not exactly sure how the problem is solved. I mean this may be answering my own question, but is it supposed to be assumed that after one of the threads return an answer, terminate? And if that is the case, why would adding synchronize make a difference?
I read (from some random PDF) that if you have two Threads start() subsequently, you cannot guarantee that the first thread will occur before the second thread. How would you guarantee it, though?
In synchronization statements, I am not completely sure whats the point of adding synchronized within the method. What is wrong with leaving it out? Is it because one expects both to mutate separately, but to be obtained together? Why not just have the two non-synchronized?
Is volatile just a keyword for variables and is synonymous with synchronized?
In the deadlock problem, how does synchronize even help the situation? What makes this situation different from starting two threads that change a variable?
Moreover, where is the "wait"/lock for the other person to bowBack? I would have thought that bow() was blocked, not bowBack().
I'll stop here because I think if I went any further without these questions answered, I will not be able to understand the later lessons.
Answers:
Yes, a process is an operating system process that has an address space, a thread is a unit of execution, and there can be multiple units of execution in a process.
The interrupt() method and InterruptedException are generally used to wake up threads that are waiting to either have them do something or terminate.
Synchronizing is a form of mutual exclusion or locking, something very standard and required in computer programming. Google these terms and read up on that and you will have your answer.
True, this cannot be guaranteed, you would have to have some mechanism, involving synchronization that the threads used to make sure they ran in the desired order. This would be specific to the code in the threads.
See answer to #3
Volatile is a way to make sure that a particular variable can be properly shared between different threads. It is necessary on multi-processor machines (which almost everyone has these days) to make sure the value of the variable is consistent between the processors. It is effectively a way to synchronize a single value.
Read about deadlocking in more general terms to understand this. Once you first understand mutual exclusion and locking you will be able to understand how deadlocks can happen.
I have not read the materials that you read, so I don't understand this one. Sorry.
I find that the examples used to explain synchronization and volatility are contrived and difficult to understand the purpose of. Here are my preferred examples:
Synchronized:
private Value value;
public void setValue(Value v) {
value = v;
}
public void doSomething() {
if(value != null) {
doFirstThing();
int val = value.getInt(); // Will throw NullPointerException if another
// thread calls setValue(null);
doSecondThing(val);
}
}
The above code is perfectly correct if run in a single-threaded environment. However with even 2 threads there is the possibility that value will be changed in between the check and when it is used. This is because the method doSomething() is not atomic.
To address this, use synchronization:
private Value value;
private Object lock = new Object();
public void setValue(Value v) {
synchronized(lock) {
value = v;
}
}
public void doSomething() {
synchronized(lock) { // Prevents setValue being called by another thread.
if(value != null) {
doFirstThing();
int val = value.getInt(); // Cannot throw NullPointerException.
doSecondThing(val);
}
}
}
Volatile:
private boolean running = true;
// Called by Thread 1.
public void run() {
while(running) {
doSomething();
}
}
// Called by Thread 2.
public void stop() {
running = false;
}
To explain this requires knowledge of the Java Memory Model. It is worth reading about in depth, but the short version for this example is that Threads have their own copies of variables which are only sync'd to main memory on a synchronized block and when a volatile variable is reached. The Java compiler (specifically the JIT) is allowed to optimise the code into this:
public void run() {
while(true) { // Will never end
doSomething();
}
}
To prevent this optimisation you can set a variable to be volatile, which forces the thread to access main memory every time it reads the variable. Note that this is unnecessary if you are using synchronized statements as both keywords cause a sync to main memory.
I haven't addressed your questions directly as Francis did so. I hope these examples can give you an idea of the concepts in a better way than the examples you saw in the Oracle tutorial.
Having some line of statements, is there a simple way to assure it is executed in atomic way?
Atomic? No. Despite what people are saying here, thread-safe doesn't mean atomic:
// this is NOT atomic!
synchronized(this) {
makeChangeA();
makeChangeB();
}
if makeChangeB() throws an exception, makeChangeA() will not rollback it's change.
Definition of atomic is "executed either completely, or not at all". Synchronized block is not atomic.
If your emphasis is on "simple way", you can try out the #Synchronized annotation of Project Lombok.
synchronized (obj)
{
//any other thread synchronizing against obj waits until this block is done
}
Edit:
As road to yamburg mentioned, this is not atomicity; I had assumed you simply wanted to ensure that two blocks do not overlap in execution. If in fact you are looking for an atomic action, then you need to employ the user of transactions, which are by no means easy. See Atomicity and Transaction Processing for more info.
Furthermore, if you're guaranteeing atomicity, chances are you're also looking for consistency, isolation, and durability, collectively known as the ACID properties. These are also explained on the second page in detail.
As mentioned by others, synchronized does not provide true atomicity. However, it depends on what you want to achieve? If you’re interested in mutual exclusion only, than a synchronized block may help you very well.
Some atomic operations, however, are possible. Have a look at the package java.util.concurrent.atomic, which, for example, provides atomicIntegers which may be incremented atomically and retrieved in one step.
Otherwise you’ll need to implement your own solution, like with Semaphors which halt all other threads. But note, that even if you achieve to to block all other threads of your process their might as well other processes which interfere with what you are doing (I’m speaking of other OS processes, not only those running at the JVM).
But truly, what do you want to achieve? I’m pretty sure most daily use cases can be be tackled with synchronized blocks / methods and/or the mentioned atomic-pacakge.
put them in a synchronized block, then it is atomic for the JVM.
public class MyClass {
//the English word is synchronizer, not syncronisator
private static final Object syncronisator = new Object();
public void doSomething() {
doSomethingNotSyncronized();
synchronized(syncronisator) {
doItAtomic1():
doItAtomic2():
}
doSomethingNotSyncronized2();
}
}
BTW: if you want to synchronize the complete method with the instance of MyClass, then you could use:
public class MyClass {
public void synchronized doSomething() {
doItAtomic1():
doItAtomic2():
}
}
Edit:
Road to yamburg is right, atomic is not only synchronization, but mean also everything or none.