Breaking Concurrent Code - java

Let's say I have the following class:
public class BuggyClass {
private String failField = null;
public void create() {
destroy();
synchronized (this) {
failField = new String("Ou! la la!");
}
}
public void destroy() {
synchronized (this) {
failField = null;
}
}
public long somethingElse() {
if (failField == null) {
return -1;
}
return failField.length();
}
}
It's easy to see that in a multithreaded execution of the above code we could get a NullPointerExeption in somethingElse. For example, it could be that failField != null and before returning failField.length() destroy gets called therefore making failField to null.
I want to create a multithreaded program that is going to be able to "throw" a NullPointerException when using BuggyClass. I know, that since the program is multithreaded, it could be that this never happens but I guess there should be some better test that increases the probability of getting an exception. Right?
I tried the following:
final BuggyClass bc = new BuggyClass();
final int NUM_OF_INV = 10000000;
int NUM_OF_THREADS = 5;
ExecutorService executor = Executors.newFixedThreadPool(3 * NUM_OF_THREADS);
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.create();
}
}
});
}
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.destroy();
}}
});
}
for (int i = 0; i < (NUM_OF_THREADS); ++i) {
executor.submit(new Runnable() {
public void run() {
for(int i = 0; i< NUM_OF_INV; i++){
bc.somethingElse();
}}
});
}
executor.shutdown(); executor.awaitTermination(1, TimeUnit.DAYS);
I executed the above code (method) multiple times with different NUM_OF_INV and NUM_OF_THREADS but NEVER managed to get a NullPointerException.
Any ideas on how I can create a test that increases my chances of getting an exception without changing BuggyClass?

Although there is a data race in your code, it might be impossible to see any problems, that are caused by this data race. Most likely, the JIT compiler will transform the method somethingElse into something like this:
public long somethingElse() {
String reg = failField; // load failField into a CPU register
if (reg == null) {
return -1;
}
return reg.length();
}
That means, the compiler will not load the reference failField after the condition. And it is impossible to trigger the NullPointerException.
Update: I have compiled the method somethingElse with GCJ to see some real and optimized assembler output. It looks as follows:
long long BuggyClass::somethingElse():
movq 8(%rdi), %rdi
testq %rdi, %rdi
je .L14
subq $8, %rsp
call int java::lang::String::length()
cltq
addq $8, %rsp
ret
.L14:
movq $-1, %rax
ret
You can see from this code, that the reference failField is loaded once. Of course, there is no guarantee, that all implementations will use the same optimization now and forever. So, you shouldn't rely on it.

It does fail... on my machine at least. The thing is that the Runnable swallows the exception. Try instead:
executor.submit(new Runnable() {
public void run() {
for (int i = 0; i < NUM_OF_INV; i++) {
try {
bc.somethingElse();
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
});
I get NPE's every time I run it.

If you just want to see the problem, you could add short sleeps before you call failField.length() and also immediately after the failField = null in the destroy() method. This would widen the window for the somethingElse() method to access the variable in a null state.

I'm surprised that nobody has noticed the fact that "failedField" was not prefixed with a volatile keyword.
While it's true there is an opportunity for a race to occur in the create() method, the reason why it probably works on other people's machines is the fact that "failedField" was not in shared memory and a cached value of "failedField" was used instead.
Also, references on 64 bit machines aren't as threadsafe as you think. That's why AtomicReference exists in java.util.concurrent

Related

Java: Is volatile access necessary when threads set different cells of an array?

Consider the following code:
public static void main(String[] args) throws InterruptedException {
int nThreads = 10;
MyThread[] threads = new MyThread[nThreads];
AtomicReferenceArray<Object> array = new AtomicReferenceArray<>(nThreads);
for (int i = 0; i < nThreads; i++) {
MyThread thread = new MyThread(array, i);
threads[i] = thread;
thread.start();
}
for (MyThread thread : threads)
thread.join();
for (int i = 0; i < nThreads; i++) {
Object obj_i = array.get(i);
// do something with obj_i...
}
}
private static class MyThread extends Thread {
private final AtomicReferenceArray<Object> pArray;
private final int pIndex;
public MyThread(final AtomicReferenceArray<Object> array, final int index) {
pArray = array;
pIndex = index;
}
#Override
public void run() {
// some entirely local time-consuming computation...
pArray.set(pIndex, /* result of the computation */);
}
}
Each MyThread computes something entirely locally (without need to synchronize with other threads) and writes the result to its specific array cell. The main thread waits until all MyThreads have finished, and then retrieves the results and does something with them.
Using the get and set methods of AtomicReferenceArray provides a memory ordering which guarantees that the main thread will see the results written by the MyThreads.
However, since every array cell is written only once, and no MyThread has to see the result written by any other MyThread, I wonder if these strong ordering guarantees are actually necessary or if the following code, with plain array cell accesses, would be guaranteed to always yield the same results as the code above:
public static void main(String[] args) throws InterruptedException {
int nThreads = 10;
MyThread[] threads = new MyThread[nThreads];
Object[] array = new Object[nThreads];
for (int i = 0; i < nThreads; i++) {
MyThread thread = new MyThread(array, i);
threads[i] = thread;
thread.start();
}
for (MyThread thread : threads)
thread.join();
for (int i = 0; i < nThreads; i++) {
Object obj_i = array[i];
// do something with obj_i...
}
}
private static class MyThread extends Thread {
private final Object[] pArray;
private final int pIndex;
public MyThread(final Object[] array, final int index) {
pArray = array;
pIndex = index;
}
#Override
public void run() {
// some entirely local time-consuming computation...
pArray[pIndex] = /* result of the computation */;
}
}
On the one hand, under plain mode access the compiler or runtime might happen to optimize away the read accesses to array in the final loop of the main thread and replace Object obj_i = array[i]; with Object obj_i = null; (the implicit initialization of the array) as the array is not modified from within that thread. On the other hand, I have read somewhere that Thread.join makes all changes of the joined thread visible to the calling thread (which would be sensible), so Object obj_i = array[i]; should see the object reference assigned by the i-th MyThread.
So, would the latter code produce the same results as the above?
So, would the latter code produce the same results as the above?
Yes.
The "somewhere" that you've read about Thread.join could be JLS 17.4.5 (The "Happens-before order" bit of the Java Memory Model):
All actions in a thread happen-before any other thread successfully returns from a join() on that thread.
So, all of your writes to individual elements will happen before the final join().
With this said, I would strongly recommend that you look for alternative ways to structure your problem that don't require you to be worrying about the correctness of your code at this level of detail (see my other answer).
An easier solution here would appear to be to use the Executor framework, which hides typically unnecessary details about the threads and how the result is stored.
For example:
ExecutorService executor = ...
List<Future<Object>> futures = new ArrayList<>();
for (int i = 0; i < nThreads; i++) {
futures.add(executor.submit(new MyCallable<>(i)));
}
executor.shutdown();
for (int i = 0; i < nThreads; ++i) {
array[i] = futures.get(i).get();
}
for (int i = 0; i < nThreads; i++) {
Object obj_i = array[i];
// do something with obj_i...
}
where MyCallable is analogous to your MyThread:
private static class MyCallable implements Callable<Object> {
private final int pIndex;
public MyCallable(final int index) {
pIndex = index;
}
#Override
public Object call() {
// some entirely local time-consuming computation...
return /* result of the computation */;
}
}
This results in simpler and more-obviously correct code, because you're not worrying about memory consistency: this is handled by the framework. It also gives you more flexibility, e.g. running it on fewer threads than work items, reusing a thread pool etc.
Atomic operations are required to ensure memory barriers are present when multiple threads access the same memory location. Without memory barriers, there is no happened-before relationship between the threads and there is no guarantee that the main thread will see the modifications done by the other threads, hence data rance. So what you really need is memory barriers for the write and read operations. You can achieve that using AtomicReferenceArray or a synchronized block on a common object.
You have Thread.join in the second program before the read operations. That should remove the data race. Without the join, you need explicit synchronization.

Sharing variable between threads in JAVA

I have two threads doing calculation on a common variable "n", one thread increase "n" each time, another decrease "n" each time, when I am not using volatile keyword on this variable, something I cannot understand happens, sb there please help explain, the snippet is like follow:
public class TwoThreads {
private static int n = 0;
private static int called = 0;
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
n = 0;
called = 0;
TwoThreads two = new TwoThreads();
Inc inc = two.new Inc();
Dec dec = two.new Dec();
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
while (called != 2) {
//System.out.println("----");
}
System.out.println(n);
}
}
private synchronized void inc() {
n++;
called++;
}
private synchronized void dec() {
n--;
called++;
}
class Inc implements Runnable {
#Override
public void run() {
inc();
}
}
class Dec implements Runnable {
#Override
public void run() {
dec();
}
}
}
1) What I am expecting is "n=0,called=2" after execution, but chances are the main thread can be blocked in the while loop;
2) But when I uncomment this line, the program when as expected:
//System.out.println("----");
3) I know I should use "volatile" on "called", but I cannot explain why the above happens;
4) "called" is "read and load" in working memory of specific thread, but why it's not "store and write" back into main thread after "long" while loop, if it's not, why a simple "print" line can make such a difference
You have synchronized writing of data (in inc and dec), but not reading of data (in main). BOTH should be synchronized to get predictable effects. Otherwise, chances are that main never "sees" the changes done by inc and dec.
You don't know where exactly called++ will be executed, your main thread will continue to born new threads which will make mutual exclusion, I mean only one thread can make called++ in each time because methods are synchronized, and you don't know each exactly thread will be it. May be two times will performed n++ or n--, you don't know this, may be ten times will performed n++ while main thread reach your condition.
and try to read about data race
while (called != 2) {
//System.out.println("----");
}
//.. place for data race, n can be changed
System.out.println(n);
You need to synchronize access to called here:
while (called != 2) {
//System.out.println("----");
}
I sugest to add getCalled method
private synchronized int getCalled() {
return called;
}
and replace called != 2 with getCalled() != 2
If you interested in why this problem occure you can read about visibility in context of java memory model.

Java-threadPool - synchronize Threds

edit: 1.) Why is "globalCounter" synchronized , but not "Thread.currentThread().getId()"
2.) Can I assign a calculation to each thread? how? Can i work with the results?
public class Hauptprogramm {
public static final int MAX_THREADS = 10;
public static int globalCounter;
public static Integer syncObject = new Integer(0);
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(MAX_THREADS);
for (int i = 0; i < MAX_THREADS; i++) {
threadPool.submit(new Runnable() {
public void run() {
synchronized (syncObject) {
globalCounter++;
System.out.println(globalCounter);
System.out.println(Thread.currentThread().getId());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}});
}
threadPool.shutdown();
}
}
1.) Why is "globalCounter" synchronized , but not "Thread.currentThread().getId()"
I can answer why globalCounter is synchronized. To avoid data race and race condition.
In case if it is not synchronized - globalCounter++ computation is a three step process (Read-Modify-Write) -
Read the current value of globalCounter varaible.
Modify its value.
Write/ Assign the modified value back to the globalCounter.
In the absence of synchronization in multi threaded environment, there is a possibility that a thread might read/ modifies the value of globalCounter when another thread is in the mid of this 3 step process.
This can result into thread/s reading stale values or loss of update count.
2) Can I assign a calculation to each thread? how? Can i work with the results?
This is possible. You can look into Future/ FutureTask to work with the result

Why does a concurrent hash map work properly when accessed by two thread, one using the clear() and other using the putifAbsent() methods?

I am implementing an application using concurrent hash maps. It is required that one thread adds data into the CHM, while there is another thread that copies the values currently in the CHM and erases it using the clear() method. When I run it, after the clear() method is executed, the CHM always remains empty, though the other thread continues adding data to CHM.
Could someone tell me why it is so and help me find the solution.
This is the method that adds data to the CHM. This method is called from within a thread.
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
public static ConcurrentMap<String, String> updateJobList = new ConcurrentHashMap<String, String>(8, 0.9f, 6);
public void setUpdateQuery(String ticker, String query)
throws RemoteException {
dataBaseText = "streamming";
int n = 0;
try {
updateJobList.putIfAbsent(ticker, query);
}
catch(Exception e)
{e.printStackTrace();}
........................
}
Another thread calls the track_allocation method every minute.
public void track_allocation()
{
class Track_Thread implements Runnable {
String[] track;
Track_Thread(String[] s)
{
track = s;
}
public void run()
{
}
public void run(String[] s)
{
MonitoringForm.txtInforamtion.append(Thread.currentThread()+"has started runnning");
String query = "";
track = getMaxBenefit(track);
track = quickSort(track, 0, track.length-1);
for(int x=0;x<track.length;x++)
{
query = track[x].split(",")[0];
try
{
DatabaseConnection.insertQuery(query);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
joblist = updateJobList.values();
MonitoringForm.txtInforamtion.append("\nSize of the joblist is:"+joblist.size());
int n = joblist.size()/6;
String[][] jobs = new String[6][n+6];
MonitoringForm.txtInforamtion.append("number of threads:"+n);
int i = 0;
if(n>0)
{
MonitoringForm.txtInforamtion.append("\nSize of the joblist is:"+joblist.size());
synchronized(this)
{
updateJobList.clear();
}
Thread[] threads = new Thread[6];
Iterator it = joblist.iterator();
int k = 0;
for(int j=0;j<6; j++)
{
for(k = 0; k<n; k++)
{
jobs[j][k] = it.next().toString();
MonitoringForm.txtInforamtion.append("\n\ninserted into queue:\n"+jobs[j][k]+"\n");
}
if(it.hasNext() && j == 5)
{
while(it.hasNext())
{
jobs[j][++k] = it.next().toString();
}
}
threads[j] = new Thread(new Track_Thread(jobs[j]));
threads[j].start();
}
}
}
I can see a glaring mistake. This is the implementation of your Track_Thread classes run method.
public void run()
{
}
So, when you do this:
threads[j] = new Thread(new Track_Thread(jobs[j]));
threads[j].start();
..... the thread starts, and then immediately ends, having done absolutely nothing. Your run(String[]) method is never called!
In addition, your approach of iterating the map and then clearing it while other threads are simultaneously adding is likely to lead to entries occasionally being removed from the map without the iteration actually seeing them.
While I have your attention, you have a lot of style errors in your code:
The indentation is a mess.
You have named your class incorrectly: it is NOT a thread, and that identifier ignores the Java identifier rule.
Your use of white-space in statements is inconsistent.
These things make your code hard to read ... and to be frank, they put me off trying to really understand it.

Create a simple queue with Java threads

I'm trying to create a simple queue with Java Thread that would allow a loop, say a for loop with 10 iterations, to iterate n (< 10) threads at a time and wait until those threads are finished before continuing to iterate.
Here's a better way to illustrate my problem:
for (int i = 1; i <= 10; i++) {
new Thread ( do_some_work() );
if ( no_available_threads ) {
wait_until_available_threads();
}
}
do_some_work() {
// do something that takes a long time
}
Basically what I want to do is a copy of this: Thread and Queue
How can I achieve this the most painless way?
I would use the Java 5 Executors instead of rolling your own. Something like the following:
ExecutorService service = Executors.newFixedThreadPool(10);
// now submit our jobs
service.submit(new Runnable() {
public void run() {
do_some_work();
}
});
// you can submit any number of jobs and the 10 threads will work on them
// in order
...
// when no more to submit, call shutdown, submitted jobs will continue to run
service.shutdown();
// now wait for the jobs to finish
service.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
Use the Executors, as recommended by the others. However, if you want the fun of doing it yourself, try something like this. (Take care. I wrote it in Notepad and there's some Exceptions you'll need to catch even if I got everything else right. Notepad's poor at catching coding errors.) This is more a concept than an actual solution to anything, but the idea could be generally useful.
private ConcurrentLinkedQueue<MyThread> tQueue =
new ConcurrentLinkedQueue<MyThread>();
class MyThread extends Thread {
public Runnable doSomething;
public void run() {
// Do the real work.
doSomething();
// Clean up and make MyThread available again.
tQueue.add( mythread );
// Might be able to avoid this synch with clever code.
// (Don't synch if you know no one's waiting.)
// (But do that later. Much later.)
synchronized (tQueue) {
// Tell them the queue is no longer empty.
tQueue.notifyAll();
}
}
}
Elsewhere:
// Put ten MyThreads in tQueue.
for (int i = 0; i < 10; i++) tQueue.add( new MyThread() );
// Main Loop. Runs ten threads endlessly.
for (;;) {
MyThread t = tQueue.poll();
if (t == null) {
// Queue empty. Sleep till someone tells us it's not.
do {
// There's a try-catch combo missing here.
synchonized( tQueue ) { tQueue.wait() };
t = tQueue.poll();
} while (t == null) break; // Watch for fake alert!
}
t.doSomething = do_some_work;
t.start();
}
Also, note the clever use of ConcurrentLinkedQueue. You could use something else like ArrayList or LinkedList, but you'd need to synchronize them.
see java.util.concurrent and especially Executors and ExecutorService
Crate Logger.class :
public class Logger extends Thread {
List<String> queue = new ArrayList<String>();
private final int MAX_QUEUE_SIZE = 20;
private final int MAX_THREAD_COUNT = 10;
#Override
public void start() {
super.start();
Runnable task = new Runnable() {
#Override
public void run() {
while (true) {
String message = pullMessage();
Log.d(Thread.currentThread().getName(), message);
// Do another processing
}
}
};
// Create a Group of Threads for processing
for (int i = 0; i < MAX_THREAD_COUNT; i++) {
new Thread(task).start();
}
}
// Pulls a message from the queue
// Only returns when a new message is retrieves
// from the queue.
private synchronized String pullMessage() {
while (queue.isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
}
}
return queue.remove(0);
}
// Push a new message to the tail of the queue if
// the queue has available positions
public synchronized void pushMessage(String logMsg) {
if (queue.size() < MAX_QUEUE_SIZE) {
queue.add(logMsg);
notifyAll();
}
}
}
Then insert bellow code in your main class :
Logger logger =new Logger();
logger.start();
for ( int i=0; i< 10 ; i++) {
logger.pushMessage(" DATE : "+"Log Message #"+i);
}

Categories