atomic question from core java - java

This is a section from Core Java 8th edition Page 757
CAUTION:
public void flipDone() {
done = !done;
}
// not atomic
I don't understand why it's not atomic. Can any one tell me why? thanks

The flipDone method is executed by the computer in three distinct steps:
Read the value of memory location labeled done into ALU
Flip the value (i.e true -> false or false -> true)
Write the new value into the memory location done
In Java, a piece of code can potentially be invoked in multiple threads. These threads should be thought of as executing the code concurrently.
Say, memory location labeled done contains the value false initially. Consider two threads calling flipDone, resulting in the following sequence of steps:
Thread 1 Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true
Write the new value, true, to done
Read value of done, now true
Invert that value to false
Write the new value, false, to done
The flipDone method was called twice. done went from false to true and then back again to false - as one would expect. But since the threads execute concurrently, this is not the only ordering of steps. Consider this ordering instead:
Thread 1 Thread 2
-----------------------------------------------------------------------
Read value of done, false
Invert that value to true Read value of done, false
Write the new value, true, to done Invert that value to true
Write the new value, true, to done
While the first thread is inverting the value it read, the second thread, concurrently, is reading the value. Similarly, while the first thread is writing the value to memory, the second thread is inverting the value it read. When Thread 2 finishes, the value of done will be true. Here, although flipDone was called twice, done was flipped only once! One of the updates seem to have been lost. This is the problem that the book is trying to warn you about.

There are three steps here:
Read the value of the boolean done
Invert the value read in step 1
Assign that value to the boolean done
There's nothing to stop another thread from pre-empting in the middle of all this.

Because two threads may be calling flipDone() method at the same time so the state of the done variable is indeterminate.

When you execute
done = !done;
What actually happens is:
1. Get the value of done
2. Apply the not operator
3. Assign it to done
If two threads execute the first step together, they are going to have the same value of done, so instead of changing it two times, they will change it only once.
For instance if done was initially true, after changing it two times you'd expect it's still true, but if the two threads execute step 1 together, it will be false.

It does not execute as a single indivisible operation but instead is a sequence of three discrete operations - Fetch the current value of done, Negate the value, Write the new value back to done. It is a read-modify-write operation in which the resulting state is derived from the previous state.

Related

guava - bloomfilter: is it possible to get a true-negative for a value that was **previously** a false-positive?

If I understand correctly, once an item is put inside a guava bloom filter, mightContain will always return true. If the filter returns false on mightContain, then the value has never been put inside the filter. What I'm wondering is for the values that might be a false positive at a given moment, as more values are put in, the once false-positives might become true-negatives later on (if they are not put in, of course).
Something like this:
GuavaBloomFilter<Integer> bf = new GuavaBloomFilter<>(blah, blah);
# if I start checking, none of the values should return tru at the monent
System.out.println(bd.mightContain(5)); // false
System.out.println(bd.mightContain(10)); // false
System.out.println(bd.mightContain(15)); // false
# fine
# let's put in a value now
bf.put(10);
System.out.println(bd.mightContain(5));
System.out.println(bd.mightContain(10)); // true, every time from now on
System.out.println(bd.mightContain(15));
On the last 3 checks, when checking for 10, it will always return true. For 5 and 15, it might return true. Suppose that for 5 we get false (never put inside), for 15 we get a false positive.
So, we continue:
bf.put(5);
System.out.println(bd.mightContain(5)); // true, every single time from now on
System.out.println(bd.mightContain(10)); // true, every time from now on
System.out.println(bd.mightContain(15));
So.... now, when checking for 5, we will always get true. Is it possible that because of the state change inside the bloom filter, the result for checking 15 which was previously a false-positive, might return a true-negative value?
For a true Bloom filter, the bits only ever go from 0 to 1, never back - so the result of a mightContain call can only ever go from false to true, never back, because mightContain returns true if a certain subset of all bits are 1, and once they're 1 they'll stay 1.
Guava's implementation is indeed a true Bloom filter, since the BloomFilter.put method (source) delegates to Strategy.put (source), an interface implemented in BloomFilterStrategies (source). The Bloom filter's bits are stored in a LockFreeBitArray named bits, and the strategy only calls its bitSize, set and get methods. Of those, only set changes bits (source), and it only uses the bitwise 'or' operator | to change them. This can never change a 1 back to a 0.
So, it is indeed impossible for a value which was previously a false-positive to later become a true-negative.

Java parallel volatile i++

I have a global variable
volatile i = 0;
and two threads. Each does the following:
i++;
System.out.print(i);
I receive the following combinations. 12, 21 and 22.
I understand why I don't get 11 (volatile disallows the caching of i) and I also understand 12 and 22.
What I don't understand is how it is possible to get 21?
The only possible way how you can get this combination is that the thread that prints later had to be the first to increment i from 0 to 1 and then cached i==1. Then the other thread incremented i from 1 to 2 and then printed 2. Then the first thread prints the cached i==1. But I thought that volatile disallow caching.
Edit: After running the code 10,000 times I got 11 once. Adding volatile to i does not change the possible combinations at all.
markspace is right: volatile forbids caching i but i++ is not atomic. This means that i still gets sort of "cached" in a register during the incrementation.
r1 = i
//if i changes here r1 does not change
r1 = r1 + 1
i = r1
This is the reason why 11 is still possible. 21 is caused because PrintStreams are not synchronized (see Karol Dowbecki's answer)
Your code does not guarantee which thread will call System.out first.
The increments and reads for i happened in order due to volatile keyword but prints didn't.
Unfortunately ++ is not an atomic operation. Despite volatile not allowing caching, it is permitted for the JVM to read, increment, and then write as separate operations. Thus, the concept you are trying to implement just isn't workable. You need to use synchronized for its mutex, or use something like AtomicInteger which does provide an atomic increment operation.
The only possible way...is that the thread that prints later had to be the first to increment i from 0 to 1 and then cached i==1...
You are forgetting about what System.out.print(i); does: That statement calls the System.out object's print(...) method with whatever value was stored in i at the moment when the call was started.
So here's one scenario that could happen:
Thread A
increments i (i now equals 1)
Starts to call `print(1)` //Notice! that's the digit 1, not the letter i.
gets bogged down somewhere deep in the guts...
Thread B
increments i (i=2)
Calls `print(2)`
Gets lucky, and the call runs to completion.
Thread A
finishes its `print(1)` call.
Neither thread is caching the i variable. But, the System.out.print(...) function doesn't know anything about your volatile int i. It only knows about the value (1 or 2) that was passed to it.

RxJava 2 operator combination that delivers only the first Value from a bunch

The idea is when I call publishSubject.onNext(someValue) multiple times I need to get only one value like debounce operator does, but it delivers the last value, and I need to skip all values except first in a bunch till I stop calling onNext() for 1 sec.
I've tried to use something like throttleFirst(1000,TimeUnit.MILLISECONDS) but it's not working like debounce, it just makes windows after every delivery and after 1 sec immediate deliver next value.
Try this:
// Observable<T> stream = ...;
stream.window(stream.debounce(1, TimeUnit.Seconds))
.flatMap(w -> w.take(1));
Explanation: If I understand you correctly, you want to emit items if none have been emitted for 1 second prior. This is equivalent to getting the first element following an item debounced by 1 second. The below marble diagram may also help:
You can use the first operator. Like:
Observable.first()
It will take only the first value

SelectOutput malfunctioning

Using a selectOutput I'm facing a problem (I think it's a malfunction).
The condition is as follows:
main.controlLot[agent.orderID][workcenterID]==
main.alreadyEntered[agent.orderID][workcenterID] ||
agent.numberProductsInPallet ==
((int) selectFrom(routings)
.where(routings.work_center.eq(Name))
.where(routings.component_id.eq(agent.component))
.firstResult(routings.palletization))
On enter I'm checking self.condition(agent) and when it is verified by the first segment of the condition (main.controlLot[agent.orderID][workcenterID]==main.alreadyEntered[agent.orderID][workcenterID]) it does not go through the True port. However, self.condition(agent) returns True.
I placed the following code on exit (False) to confirm if the condition could change mid logic:
traceln(main.controlLot[agent.orderID][workcenterID] + " " + main.alreadyEntered[agent.orderID][workcenterID]);
traceln(agent.numberProductsInPallet);
traceln(self.condition(agent));
and the traceln(self.condition(agent) prints true. I don't understand why would it evaluate the condition as true but send the agent through the false port.
it might be related to the type of system you use.
if you use the "pull" protocol (see: http://www.anylogic.com/blog?page=post&id=157) the agent will look ahead and evaluate the selectoutput, before it enters it. Since the time spent in the selectoutput object is 0, it has to do that.
if the condition changes after it has evaluated the selectoutput function, it will still choose the false path even though it's true.
to fix it, depending on your code, you could use a queue object. This will give the agent 1 additional timestep to relax the parameters and evaluate the condition correctly

Simple Multi Thread code to be clarified

I've got this little problem on thread.
int x = 0;
add() {
x=x+1;
}
If we run this in multiple threads, say 4 threads, is the final value of x=4 at every time or it could be 1,2,3 or 4.
Thanks
PS
lets say the atomic operations for the adding is like this,
LOAD A x
ADD A 1
LOAD x A
Then the final result will be 4. Am I right or what have I get wrong ?
This is a classical example of data race.
Now, let's take a closer look at what add() does:
add()
{
x = x + 1;
}
This translates to:
Give me the most recent value of X and store it in my private workspace
Add 1 to that value that is stored in my private workspace
Copy what I have in my workspace to the memory that I copied from (that is globally accessible).
Now, before we go further in explaining this, you have something called context switch, which is the process by which your operating system divides your processor's time among different threads and processes. This process usually gives your threads a finite amount of processor time (on windows it is about 40 milliseconds) and then interrupts that work, copies everything the processor have in its registers (and by thus preserve it's state) and switch to the next task. This is called Round-robin task scheduling.
You have no control over when you're processing is going to be interrupted and transferred to another thread.
Now imagine you have two threads doing the same:
1. Give me the most recent value of X and store it in my private workspace
2. Add 1 to that value that is stored in my private workspace
3. Copy what I have in my workspace to the memory that I copied from (that is globally accessible).
and X is equal to 1 before any of them runs.
The first thread might execute the first instruction and store in it's private workspace the value of X that was most recent at the time it was working on - 1. Then a context-switch occurs and the operating system interrupts your threads and gives control to the next task in queue, that happens to be the second thread. The second thread also reads the value of X which is equal to 1.
Thread number two manages to run to completion - it adds 1 to the value it "downloaded" and "uploads" the calculated value.
The operating system forces a context switch again.
Now the first thread continues execution at the point where it was interrupted. It will still think that the most recent value is 1, it will increment that value by one and save the result of it's computation to that memory area. And this is how data races occur. You expect the final result to be 3 but it is 2.
There are many ways to avoid this problem such as locks/mutexes, compare and swap or atomic operations.
Your code is broken at two levels:
No happens-before relationship imposed between actions of threads;
Atomicity of get-and-increment not enforced.
To solve 1. you can add the volatile modifier. This will still leave the operation non-atomic. To ensure atomicity, you would use (preferably) an AtomicInteger or synchronized (involves locking, not preferred).
As it stands, the result can be any number from 0 to 4 if read from a thread that was not involved in incrementing.
Multi-thread applications are concurrent (this is the whole point).
t1: LOAD A1 x
t2: LOAD A2 x
t3: LOAD A3 x
t4: LOAD A4 x
t1: ADD A1 1
t2: ADD A2 1
t3: ADD A3 1
t4: ADD A4 1
t1: STORE x A1
t2: STORE x A2
t3: STORE x A3
t4: STORE x A4
A1, A2, A3, A4 are local registers.
The result is 1, but it could be 2, 3 or 4. If you have another thread it could see the old value due to visability issues and see 0

Categories

Resources