Are unsynchronized reads (combined with synchronized writes) eventually consistent - java

I have a use case with many writer threads and a single reader thread. The data being written is an event counter which is being read by a display thread.
The counter only ever increases and the display is intended for humans, so the exact point-in-time value is not critical. For this purpose, I would consider a solution to be correct as long as:
The value seen by the reader thread never decreases.
Reads are eventually consistent. After a certain amount of time without any writes, all reads will return the exact value.
Assuming writers are properly synchronized with each other, is it necessary to synchronize the reader thread with the writers in order to guarantee correctness, as defined above?
A simplified example. Would this be correct, as defined above?
public class Eventual {
private static class Counter {
private int count = 0;
private Lock writeLock = new ReentrantLock();
// Unsynchronized reads
public int getCount() {
return count;
}
// Synchronized writes
public void increment() {
writeLock.lock();
try {
count++;
} finally {
writeLock.unlock();
}
}
}
public static void main(String[] args) {
List<Thread> contentiousThreads = new ArrayList<>();
final Counter sharedCounter = new Counter();
// 5 synchronized writer threads
for(int i = 0; i < 5; ++i) {
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 20_000; ++i) {
sharedCounter.increment();
safeSleep(1);
}
}
}));
}
// 1 unsynchronized reader thread
contentiousThreads.add(new Thread(new Runnable(){
#Override
public void run() {
for(int i = 0; i < 30; ++i) {
// This value should:
// +Never decrease
// +Reach 100,000 if we are eventually consistent.
System.out.println("Count: " + sharedCounter.getCount());
safeSleep(1000);
}
}
}));
contentiousThreads.stream().forEach(t -> t.start());
// Just cleaning up...
// For the question, assume readers/writers run indefinitely
try {
for(Thread t : contentiousThreads) {
t.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void safeSleep(int ms) {
try {
Thread.sleep(ms);
} catch (InterruptedException e) {
//Don't care about error handling for now.
}
}
}

There is no guarantee that the readers would ever see an update to the count. A simple fix is to make count volatile.
As noted in another answer, in your current example, the "Final Count" will be correct because the main thread is joining the writer threads (thus establishing a happens-before relationship). however, your reader thread is never guaranteed to see any update to the count.

JTahlborn is correct, +1 from me. I was rushing and misread the question, I was assuming wrongly that the reader thread was the main thread.
The main thread can display the final count correctly due to the happens-before relationship:
All actions in a thread happen-before any other thread successfully returns from a join on that thread.
Once the main thread has joined to all the writers then the counter's updated value is visible. However, there is no happens-before relationship forcing the reader's view to get updated, you are at the mercy of the JVM implementation. There is no promise in the JLS about values getting visible if enough time passes, it is left open to the implementation. The counter value could get cached and the reader could possibly not see any updates whatsoever.
Testing this on one platform gives no assurance of what other platforms will do, so don't think this is OK just because the test passes on your PC. How many of us develop on the same platform we deploy to?
Using volatile on the counter or using AtomicInteger would be good fixes. Using AtomicInteger would allow removing the locks from the writer thread. Using volatile without locking would be OK only in a case where there is just one writer, when two or more writers are present then ++ or += not being threadsafe will be an issue. Using an Atomic class is a better choice.
(Btw eating the InterruptedException isn't "safe", it just makes the thread unresponsive to interruption, which happens when your program asks the thread to finish early.)

Related

My java unit test failed if there is a call to wait method inside a synchronized method

I am learning multi-threads programming in java recently. And I don't understand why the following test case will fail. Any explanation will be much appreciated.
Here is MyCounter.java.
public class MyCounter {
private int count;
public synchronized void incrementSynchronized() throws InterruptedException {
int temp = count;
wait(100); // <-----
count = temp + 1;
}
public int getCount() {
return count;
}
}
This is my unit test class.
public class MyCounterTest {
#Test
public void testSummationWithConcurrency() throws InterruptedException {
int numberOfThreads = 100;
ExecutorService service = Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
MyCounter counter = new MyCounter();
for (int i = 0; i < numberOfThreads; i++) {
service.submit(() -> {
try {
counter.incrementSynchronized();
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
But if I remove wait(100) from the synchronized method incrementSynchronized, the test will succeed. I don't understand why wait(100) will affect the result.
Solomons suggestion to use sleep is a good one. If you use sleep instead of wait, you should see the test pass.
Using wait causes the thread to relinquish the lock, allowing other threads to proceed and overwrite the value in count. When the thread's wait times out, it acquires the lock again, then writes a value to count that may be stale by now.
The typical usage of wait is when your thread can't do anything useful until some condition is met. Some other thread eventually satisfies that condition and a notification gets sent that will inform the thread it can resume work. In the meantime, since there is nothing useful the thread can do, it releases the lock it is holding (because other threads need the lock in order to make progress meeting the condition that the thread is waiting for) and goes dormant.
Sleep doesn't release the lock so there won't be interference from other threads. For either the sleeping case or the case where you delete the wait call, the lock is held for the duration of the operation, nothing else can change count, so it is threadsafe.
Be aware that in real life, outside of learning exercises, sleeping with a lock held is usually not a great idea. You want to minimize the time that a task holds a lock so you can get more throughput. Threads denying each other the use of a lock is not helpful.
Also be aware that getCount needs to be synchronized as well, since it is reading a value written by another thread.

Is this synchronized block need?

Is the synchronized block on System.out.println(number); need the following code?
import java.util.concurrent.CountDownLatch;
public class Main {
private static final Object LOCK = new Object();
private static long number = 0L;
public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
synchronized (LOCK) { // Is this synchronized block need?
System.out.println(number);
}
}
private static class Worker extends Thread {
private final CountDownLatch doneSignal;
private Worker(CountDownLatch doneSignal) {
this.doneSignal = doneSignal;
}
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
}
}
I think it's need because there is a possibility to read the cached value.
But some person say that:
It's unnecessary.
Because when the main thread reads the variable number, all of worker thread has done the write operation in memory of variable number.
doneSignal.await() is a blocking call, so your main() will only proceed when all your Worker threads have called doneSignal.countDown(), making it reach 0, which is what makes the await() method return.
There is no point adding that synchronized block before the System.out.println(), all your threads are already done at that point.
Consider using an AtomicInteger for number instead of synchronizing against a lock to call += 1.
It is not necessary:
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Worker worker = new Worker(doneSignal);
worker.start();
}
doneSignal.await();
// here the only thread running is the main thread
Just before dying each thread countDown the countDownLatch
#Override
public void run() {
synchronized (LOCK) {
number += 1;
}
doneSignal.countDown();
}
Only when the 10 thread finish their job the doneSignal.await(); line will be surpass.
It is not necessary because you are waiting for "done" signal. That flush memory in a way that all values from the waited thread become visible to main thread.
However you can test that easily, make inside the run method a computation that takes several (millions) steps and don't get optimized by the compiler, if you see a value different than from the final value that you expect then your final value was not already visible to main thread. Of course here the critical part is to make sure the computation doesn't get optimized so a simple "increment" is likely to get optimized. This in general is usefull to test concurrency where you are not sure if you have correct memory barriers so it may turn usefull to you later.
synchronized is not needed around System.out.println(number);, but not because the PrintWriter.println() implementations are internally synchronized or because by the time doneSignal.await() unblocks all the worker threads have finished.
synchronized is not needed because there's a happens-before edge between everything before each call to doneSignal.countDown and the completion of doneSignal.await(). This guarantees that you'll successfully see the correct value of number.
Needed
No.
However, as there is no (documented) guarantee that there will not be any interleaving it is possible to find log entries interleaved.
System.out.println("ABC");
System.out.println("123");
could print:
AB1
23C
Worthwhile
Almost certainly not. Most JVMs will implement println with a lock open JDK does.
Edge case
As suggested by #DimitarDimitrov, there is one further possible use for that lock and it is to ensure a memory barrier is crossed befor accessing number. If that is the concern then you do not need to lock, all you need to do is make number volatile.
private static volatile long number = 0L;

synchronize two threads in java

I have two threads in my java programme, one is main thread and other thread is thread A which is spawned in main thread. now i want main thread to start thread A and wait till thread A has executed some part of its code in run method and thread A should suspend itself. main thread should then start running, run few lines of code and then again thread A should start from where it has stopped and vice versa. this should happen for n number of times.
I am trying as belows:
Thread A class:
public class ThreadA implements Runnable {
boolean suspended = false;
boolean stopped = false;
synchronized void stop() {
stopped = true;
suspended = false;
notify();
}
synchronized void suspend() {
suspended = true;
}
synchronized void resume() {
suspended = false;
notify();
}
void job() throws InterruptedException {
for (int i = 0; i < 5; i++)
synchronized (this) {
System.out.println("performing job.");
suspend();
while (suspended) {
notify();
suspended = false;
}
}
}
#Override
public void run() {
try {
job();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
MainThread:
public class MainThread {
public static void main(String[] args) throws InterruptedException {
ThreadA a1=new ThreadA();
Thread t1=new Thread(a1);
synchronized (t1) {
t1.start();
for (int i = 0; i < 5; i++) {
t1.wait();
System.out.println("perform some action");
a1.resume();
}
}
}
}
Expected output:
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
Actual output:
performing job.
performing job.
performing job.
performing job.
performing job.
perform some action
I don't know why the whole for loop is getting executed in Thread A even when i've issued a notify() signal in job method.
You have two bugs here.
The first is that you are synchronizing and notifying different objects. Try this modified main, I changed synchronized (t1) to synchronized (a1) and t1.wait() to a1.wait().
public static void main(String[] args) throws InterruptedException {
ThreadA a1=new ThreadA();
Thread t1=new Thread(a1);
synchronized (a1) { // CHANGED FROM t1 to a1
t1.start();
for (int i = 0; i < 5; i++) {
a1.wait(); // CHANGED FROM t1 to a1
System.out.println("perform some action");
a1.resume();
}
}
}
The second bug is in the job() method, it calls notify() but not wait(). Here is a fixed version:
void job() throws InterruptedException {
for (int i = 0; i < 5; i++)
synchronized (this) {
System.out.println("performing job.");
suspend();
while (suspended) {
notify();
suspended = false;
wait(); // ADDED
}
}
}
The output from my test run is
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
performing job.
perform some action
Here is more simplified way
public class TwoThread {
public static void main(String[] args) throws InterruptedException {
ThreadA a1 = new ThreadA();
Thread t1 = new Thread(a1);
synchronized (a1) {
t1.start();
for (int i = 0; i < 5; i++) {
a1.wait();
System.out.println("perform some action " + i);
a1.notify();
}
}
}
}
public class ThreadA implements Runnable {
boolean suspended = false;
boolean stopped = false;
void job() throws InterruptedException {
for (int i = 0; i < 5; i++)
synchronized (this) {
System.out.println("performing job. " + i);
notify();
wait();
}
}
public void run() {
try {
job();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
To communicate between two threads only:
You do not need synchronized
You do not need locks
You do not need CAS (Compare And Swap). (Neither weak or strong)
You do not need setOpaque, setVolative nor setRelease
You just need VarHandle barrier (in Java).
Java VarHandle
The only requirement is ordered memory access
Here is a reasonably good article.
Synchronizing without Locks and Concurrent Data
Structures
In my daily work, I use variants of Dekker's and Peterson's algorithm
for asynchronous multi-threaded processing of web requests, sharing connection pools and collecting logs from cloud application with minor impact on performance
compared to the single thread un-contended performance.
Occasionally, I have to use setOpaque and getOpaque,
with VarHandle.loadLoadFence() and VarHandle.storeStoreFence()
to ensure ordered memory access and that is all you would need.
In my view the weak CAS is the furthers I would go,
as anything else I see as a violation of the multi-core CPU architecture.
However, unless you have an in-depth understanding of the actual
hardware that you are using and memory ordering constructs
used at the micro-instruction level, I suggest you use
standard Java concurrent locks, as they are the best
and optimal for general-purpose solutions.
To achieve, 10 x performance boost over the conventional CAS algorithms,
you need to make very stable layout of all shared objects in memory
and to strictly define which threads can read
and which can write to each variable and in which order.
You will need to consider the side effect on the CPU cache
of all memory loads and stores, and then to get these
to work in your advantage on the specific platform
that you are targeting. You will end up with
quite complex algorithms, but unbeatable performance.
You should explore the LMAX Disruptor library
as it has the open source library that implements many of these concepts
like ring-buffers and single thread can write to each variable.
LMAX Disruptor User Guide
Yet, I still see this as the the conservative approach to concurrency.
My current standard is to have algorithm that tolerate racing
and discard data and repeat processing if they detect racing condition.
I use the state embeded counters, indexes, flags and hashes,
to detect thread collision and chose thread that will give up
and use another memory structure for its operation.
However, due to thread focused memory structures and
optimized reference sharing these occur rarely (like one in 1 million)
Yet, if you have good understanding of CPU cache operations
and any specialized platform instruction you can get CPU
cache to work in your advantage and execute reads and writes,
and sharing of cache lines between cores, as a side effect
of your instructions without you having to explicitly issue
commands to do this.
BTW, the NodeJS (V8) engine was an attempt to minimize contention and locking by having a single thread event loop to distribute events to all other I/O and utility library threads, so they do not have to compete between themselves for access to events and shared memory.
As you can see, NodeJS had great success,
and if we are talking about the special purpose algorithms
you can take it even further.
NodeJS architecture
Happy reading.
There is little reason to synchronize multiple threads if one threads waits while another does its thing. One could use Executors to get the same result with less work and still got the feeling that one is playing with the threads.
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
for(int i = 0; i<5;i++) {
executor.submit(new PrintTask("performing job."));
executor.submit(new PrintTask("perform some action"));
}
executor.shutdown();
}
private static class PrintTask implements Runnable {
private String string;
public PrintTask(String string) {
this.string = string;
}
#Override
public void run() {
System.out.println(string);
}
}
}

why is this thread safe?

Because it always prints out '3'. No synchronization needed? I am testing this simple thing because I am having a trouble in a real multiple thread problem, which isn't good to illustrate the problem, because it's large. This is a simplified version to showcase the situation.
class Test {
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
public void add(){
CountThread a = new CountThread();
CountThread b = new CountThread();
CountThread c = new CountThread();
a.start();
b.start();
c.start();
try {
a.join();
b.join();
c.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) {
Test test = new Test();
System.out.println("START = " + Test.count);
test.add();
System.out.println("END: Account balance = " + Test.count);
}
Because it always prints out '3'. No synchronization needed?
It is not thread safe and you are just getting lucky. If you run this 1000 times, or on different architectures, you will see different output -- i.e. not 3.
I would suggest using AtomicInteger instead of a static field ++ which is not synchronized.
public static AtomicInteger count = new AtomicInteger();
...
public void run() {
count.incrementAndGet();
}
...
Seems to me like count++ is fast enough to finish until you invoke 'run' for the other class. So basically it runs sequential.
But, if this was a real life example, and two different threads were usingCountThread parallelly, then yes, you would have synchronization problem.
To verify that, you can try to print some test output before count++ and after, then you'll see if b.start() is invoking count++ before a.start() finished. Same for c.start().
Consider using AtomicInteger instead, which is way better than synchronizing when possible -
incrementAndGet
public final int incrementAndGet()
Atomically increments by one the current value.
This code is not thread-safe:
public static int count = 0;
class CountThread extends Thread {
public void run()
{
count++;
}
}
You can run this code a million times on one system and it might pass every time. This does not mean is it is thread-safe.
Consider a system where the value in count is copied to multiple processor caches. They all might be updated independently before something forces one of the caches to be copied back to main RAM. Consider that ++ is not an atomic operation. The order of reading and writing of count may cause data to be lost.
The correct way to implement this code (using Java 5 and above):
public static java.util.concurrent.atomic.AtomicInteger count =
new java.util.concurrent.atomic.AtomicInteger();
class CountThread extends Thread {
public void run()
{
count.incrementAndGet();
}
}
It's not thread safe just because the output is right. Creating a thread causes a lot of overhead on the OS side of things, and after that it's just to be expected that that single line of code will be done within a single timeslice. It's not thread safe by any means, just not enough potential conflicts to actually trigger one.
It is not thread safe.
It just happened to be way to short to have measurable chance to show the issue. Consider counting to much higher number (1000000?) in run to increase chance of 2 operations on multiple threads to overlap.
Also make sure your machine is not single core CPU...
To make the class threadsafe either make count volatile to force memory fences between threads, or use AtomicInteger, or rewrite like this (my preference):
class CountThread extends Thread {
private static final Object lock = new Object();
public void run()
{
synchronized(lock) {
count++;
}
}
}

Volatile in java

As far as I know volatile write happens-before volatile read, so we always will see the freshest data in volatile variable. My question basically concerns the term happens-before and where does it take place? I wrote a piece of code to clarify my question.
class Test {
volatile int a;
public static void main(String ... args) {
final Test t = new Test();
new Thread(new Runnable(){
#Override
public void run() {
Thread.sleep(3000);
t.a = 10;
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
System.out.println("Value " + t.a);
}
}).start();
}
}
(try catch block is omitted for clarity)
In this case I always see the value 0 to be printed on console. Without Thread.sleep(3000); i always see value 10. Is this a case of happens-before relationship or it prints 'value 10' because thread 1 starts a bit earlier thread 2?
It would be great to see the example where the behaviour of code with and without volatile variable differs in every program start, because the result of code above depends only(at least in my case) on the order of threads and on thread sleeping.
You see the value 0 because the read is executed before the write. And you see the value 10 because the write is executed before the read.
If you want to have a test with more unpredictable output, you should have both of your threads await a CountDownLatch, to make them start concurrently:
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable(){
#Override
public void run() {
try {
latch.await();
t.a = 10;
}
catch (InterruptedException e) {
// end the thread
}
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
try {
latch.await();
System.out.println("Value " + t.a);
}
catch (InterruptedException e) {
// end the thread
}
}
}).start();
Thread.sleep(321); // go
latch.countDown();
The happens-before really has to do with a write happens before any subsequent read. If the write has not occurred yet there really is no relationship. Since the write-thread is sleeping the read is executed before the write occurs.
To observe the relationship in action you can have two variables one that is volatile and one that is not. According to the JMM it says the write to a non-volatile variable before a volatile write happens before the volatile read.
For instance
volatile int a = 0;
int b = 0;
Thread 1:
b = 10;
a = 1;
Thread 2:
while(a != 1);
if(b != 10)
throw new IllegalStateException();
The Java Memory Model says that b should always equal 10 because the non-volatile store occurs before the volatile store. And all writes that occur in one thread before a volatile store happen-before all subsequent volatile loads.
I've re-phrased (changes in bold fonts) the happens-before rule mentioned in the first sentence of your question as below so that it could be understood better -
"write of the value of a volatile variable to the main memory happens-before any subsequent read of that varible from main memory".
Also it is important to note that volatile writes/reads always
happen to/from the main memory and NOT to/from any local memory
resources like registers, processor caches etc.
The practical implication of the above happens-before rule is that all the threads that share a volatile variable will always see consistent value of that variable. No two threads see different values of that variable at any given point of time.
On the contrary, all the threads that share a non-volatile variable may see different values at any given point of time unless it is not synchronized by any other kind of synchronization mechanisms such as synchronized block/method, final keyword etc.
Now coming back to your question on this happens-before rule, i think u've slightly misunderstood that rule. The rule does not dictate that a write code should always happen (execute) before a read code. Rather it dictates that if a write code (volatile variable write) were to be executed in one thread before a read code in another thread then the effect of the write code should have happened in the main memory before the read code is executed so that the read code can see the latest value.
In the absence of volatile (or any other synchronization mechanisms), this happens-before is not mandatory, and hence a reader thread might see a stale value of non-volatile variable even though it has been recently written by a different writer thread. Because the writer thread can store the value in its local copy and need not have flushed the value to the main memory.
Hope the above explanation is clear :)
don't stick to the term 'happens-before'. it is a relation between events, used by jvm during R/W operations scheduling. at this stage it won't help you understand the volatile. the point is: jvm orders all R/W operations. jvm can order however it wants (of course obeying to all synchronize, lock, wait etc).
and now: if variable is volatile then any read operation will see the result of latest write operation. if variable is not volatile then it is not guaranteed (in different threads). that's all
piotrek is right, here is the test:
class Test {
volatile int a = 0;
public static void main(String ... args) {
final Test t = new Test();
new Thread(new Runnable(){
#Override
public void run() {
try {
Thread.sleep(3000);
} catch (Exception e) {}
t.a = 10;
System.out.println("now t.a == 10");
}
}).start();
new Thread(new Runnable(){
#Override
public void run() {
while(t.a == 0) {}
System.out.println("Loop done: " + t.a);
}
}).start();
}
}
with volatile: it will always end
without volatile: it will never end
From wiki:
In Java specifically, a happens-before relationship is a guarantee that memory written to by statement A is visible to statement B, that is, that statement A completes its write before statement B starts its read.
So if thread A write t.a with value 10 and thread B tries to read t.a some later, happens-before relationship guarantees that thread B must read value 10 written by thread A, not any other value. It's natural, just like Alice buys milk and put them into fridge then Bob opens fridge and sees the milk. However, when computer is running, memory access usually doesn't access memory directly, that's too slow. Instead, software get the data from register or cache to save time. It loads data from memory only when cache miss happens. That the problem happens.
Let's see the code in the question:
class Test {
volatile int a;
public static void main(String ... args) {
final Test t = new Test();
new Thread(new Runnable(){ //thread A
#Override
public void run() {
Thread.sleep(3000);
t.a = 10;
}
}).start();
new Thread(new Runnable(){ //thread B
#Override
public void run() {
System.out.println("Value " + t.a);
}
}).start();
}
}
Thread A writes 10 into value t.a and thread B tries to read it out. Suppose thread A writes before thread B reads, then when thread B reads it will load the value from the memory because it doesn't cache the value in register or cache so it always get 10 written by thread A. And if thread A writes after thread B reads, thread B reads initial value (0). So this example doesn't show how volatile works and the difference. But if we change the code like this:
class Test {
volatile int a;
public static void main(String ... args) {
final Test t = new Test();
new Thread(new Runnable(){ //thread A
#Override
public void run() {
Thread.sleep(3000);
t.a = 10;
}
}).start();
new Thread(new Runnable(){ //thread B
#Override
public void run() {
while (1) {
System.out.println("Value " + t.a);
}
}
}).start();
}
}
Without volatile, the print value should always be initial value (0) even some read happens after thread A writes 10 into t.a, which violate the happen-before relationship. The reason is compiler optimizes the code and save the t.a into register and every time it will use the register value instead of reading from cache memory, of course which much faster. But it also cause the happen-before relationship violation problem because thread B can't get the right value after others update it.
In the above example, volatile write happens-before volatile read means that with volatile thread B will get the right value of t.a once after thread A update it. Compiler will guarantee every time thread B reads t.a, it must read from cache or memory instead of just using register's stale value.

Categories

Resources