I'm on Java concurrency at the moment.
I don't know how to write negative scenario test.
I need a way to make deadlocks and I need a way to see that without using synchronization
I could end up with problems like inconsistency.
What is generally best way to write some stress test code
that could show me bad results if synch is omitted?
Any code example would be really appriciated.
Thank you all in advance!
The following code will almost certainly create a deadlock and demonstrates the classic deadlock scenario whereby two different threads acquire locks in an inconsistent order.
public class Main {
private final Object lockA = new Object();
private final Object lockB = new Object();
public static void main(String[] args) {
new Main();
}
public Main() {
new Thread(new Runnable() {
public void run() {
a();
sleep(3000L); // Add a delay here to increase chance of deadlock.
b();
}
}, "Thread-A").start();
new Thread(new Runnable() {
public void run() {
// Note: Second thread acquires locks in the reverse order of the first!
b();
sleep(3000L); // Add a delay here to increase chance of deadlock.
a();
}
}, "Thread-A").start();
}
private void a() {
log("Trying to acquire lock A.");
synchronized(lockA) {
log("Acquired lock A.");
}
}
private void b() {
log("Trying to acquire lock B.");
synchronized(lockB) {
log("Acquired lock B.");
}
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch(InterruptedException ex) {
}
}
private void log(String msg) {
System.err.println(String.format("Thread: %s, Message: %s",
Thread.currentThread().getName(), msg));
}
}
The following code demonstrates a situation likely to create inconsistent results due to lack of concurrency control between two threads.
public class Main {
// Non-volatile integer "result".
private int i;
public static void main(String[] args) {
new Main();
}
public Main() {
Thread t1 = new Thread(new Runnable() {
public void run() {
countUp();
}
}, "Thread-1");
Thread t2 = new Thread(new Runnable() {
public void run() {
countDown();
}
}, "Thread-2");
t1.start();
t2.start();
// Wait for two threads to complete.
t1.join();
t2.join();
// Print out result. With correct concurrency control we expect the result to
// be 0. A non-zero result indicates incorrect use of concurrency. Also note
// that the result may vary between runs because of this.
System.err.println("i: " + i);
}
private void countUp() {
// Increment instance variable i 1000,000 times. The variable is not marked
// as volatile, nor is it accessed within a synchronized block and hence
// there is no guarantee that the value of i will be reconciled back to main
// memory following the increment.
for (int j=0; j<1000000; ++j) {
++i;
}
}
private void countDown() {
// Decrement instance variable i 1000,000 times. Same consistency problems
// as mentioned above.
for (int j=0; j<1000000; ++j) {
--i;
}
}
}
In above deadlock example. Period for deadlock is 3 second. After which lockA and lockB are released and occupied by Thread 2 and Thread 1
Related
I am looking at https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility and having trouble understanding what this means - "All actions in a thread happen-before any other thread successfully returns from a join on that thread." Can I please get an example on what this means and what is the happen-before guarantee in the example.
If you have he following code
public class Test {
public static int i = 1;
public static void main(String[] args) throws Exception {
System.out.println("Start main");
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("Start second");
i = 10;
}
});
t.start();
t.join();
System.out.println("After join");
System.out.println(i); //should print 10
}
}
Everything which is done inside run() method happens before main thread gets control back from t.join();. That is why static variable i will have value 10 when printed in main thread.
I have next code:
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
// empty loop body
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
It runs infinity loop due to creation of local copy of signal variable in thread. I know that I can fix it by making my signal variable volatile. But also loop can successfully exit if add synchronized block inside my loop (even empty):
boolean signal;
#Test
public void test() throws InterruptedException {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
while (!signal){
synchronized (this) {
}
}
}
});
thread.start();
Thread.sleep(1000);
signal = true;
thread.join();
}
How synchronized updates my signal value inside thread?
Synchronized does not updates the signal value itself, it basically just places a couple of flags to avoid two threads use the same object at the same time; something like: MonitorEnter and MonitorExit.
The first one locks the object, and the second one releases.
Take a look at the following article: how-the-java-virtual-machine-performs-thread-synchronization.
Please notice the article is very old; but as far as I understand the logic behind remains.
Problem: I have collection of threads start in a loop parallelly. After exiting anyone of thread first ,all other running threads must be terminated. This is what I tried but it doesn't work. Any help is appreciated.
public class ThreadsMain {
public static void main(String[] args) {
int SIZE = 3;
Thread t[] = new Thread[SIZE];
for (int i = 0; i < SIZE; i++) {
myThreads th = new myThreads();
t[i] = new Thread(th);
t[i].start();
}
}
}
Here is one way to do it, with a synchronizer implemented with intrinsic locks, and using interruption to cancel the unfinished tasks. The data structure makes a consumer thread block until a producer has submitted a result, then it cancels the other worker threads.
This is a toy example, see the link at the end for the real-world way to do this.
First, here's a threadsafe data structure that accepts results, it allows threads to register as listeners and interrupts them once it has a result submitted to it:
class MyQueue<T> {
private java.util.List<T> results = new java.util.ArrayList<T>();
private java.util.List<Thread> listeners = new java.util.ArrayList<Thread>();
public synchronized void put(T o) {
results.add(o);
notifyAll();
for (Thread listener : listeners) {
listener.interrupt();
}
}
public synchronized T take() throws InterruptedException {
while (results.size() == 0) {
wait();
}
return results.remove(0);
}
public synchronized void addListener(Thread t) {
listeners.add(t);
}
}
(I don't like having this class know so much about the listeners but I don't want to overthink a toy example either.)
The wait method releases the lock and makes the calling thread go dormant until a notification occurs (or it can just stop waiting arbitrarily). It uses the size property of the results list to know when a result has been submitted. It's not safe to assume that because a thread stopped waiting that you can infer something about the current state, once the thread reacquires the lock it needs to check what the current state actually is. For more about how wait works see this tutorial.
Here's a task that calculates a result (sleeping between iterations just so these threads can run for a while):
class FibTask implements Runnable {
private final MyQueue<BigInteger> queue;
private final int n;
private long sleepTime;
public FibTask(int n, long sleepTime, MyQueue<BigInteger> queue) {
this.n = n;
this.sleepTime = sleepTime;
this.queue = queue;
}
#Override public void run() {
BigInteger a = BigInteger.valueOf(0);
BigInteger b = BigInteger.valueOf(1);
int i = 0;
try {
while (!Thread.currentThread().isInterrupted() && i < n) {
i = i + 1;
BigInteger temp = a;
a = b;
b = a.add(temp);
Thread.sleep(sleepTime);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (!Thread.currentThread().isInterrupted()) {
queue.put(b);
}
}
}
Notice in the code above how the Runnable needs to be aware of attempts to interrupt it. Interruption is cooperative, the task is responsible for deciding when to detect interruption and for handling the termination process.
Also if a task involves IO then in some cases interruption doesn't work and you have to close the socket, see this article for more discussion of this.
Here's the main program that runs the threads and gets the result. The MyQueue class is already doing most of the work so this doesn't have to do much:
class Completion {
public static void main(String ... args) throws Exception {
MyQueue<BigInteger> queue = new MyQueue<BigInteger>();
Thread t1 = new Thread(new FibTask(10, 1000L, queue));
Thread t2 = new Thread(new FibTask(20, 10000L, queue));
Thread t3 = new Thread(new FibTask(25, 50000L, queue));
queue.addListener(t1);
queue.addListener(t2);
queue.addListener(t3);
t1.start();
t2.start();
t3.start();
System.out.println(queue.take());
}
}
Be aware this isn't a fair race because of how the threads' starts are staggered, later threads are at a disadvantage. Submitting tasks to an Executor that initializes a threadpool up front would make sure that the time to start a thread didn't cause a delay here.
For a better way that makes use of java.util.concurrent features like Executors and Futures, see the example given in the API documentation for ExecutorCompletionService.
A simple approach, use a synchronized class to handle the loop condition:
class ThreadHandler
{
static Object lock = new Object();
static boolean finished = false;
static void finishThreads()
{
synchronized(lock)
{
finished = true;
}
}
static boolean isFinished()
{
boolean result;
synchronized(lock)
{
result = finished;
}
return result;
}
}
And in your runnable
class myThreads implements Runnable
{
#Override
public void run()
{
while(!ThreadHandler.isFinished())
{
}
}
}
Driver.java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Driver {
static Lock lock = new ReentrantLock();
static Integer incr = 20;
public static void main(String [] arg) throws InterruptedException
{
Thread thr1 = new Thread(new Runnable(){
#Override
public void run() {
lock.lock();
System.out.println("Gained access! - 1");
try {Thread.sleep(5000);} catch (InterruptedException e) {}
incr++;
lock.unlock();
}
});
Thread thr2 = new Thread(new Runnable(){
#Override
public void run() {
lock.lock();
System.out.println("Gained access! - 2");
incr++;
lock.unlock();
}
});
Thread thr3 = new Thread(new Runnable(){
#Override
public void run() {
synchronized(incr){
System.out.println("Gained access! - 3");
try {Thread.sleep(5000);} catch (InterruptedException e) {}
incr++;
}
}
});
Thread thr4 = new Thread(new Runnable(){
#Override
public void run() {
synchronized(incr){
System.out.println("Gained access! - 4");
incr++;
}
}
});
thr1.start();
thr2.start();
thr3.start();
thr4.start();
thr1.join();
thr2.join();
thr3.join();
thr4.join();
System.out.println(incr);
}
}
Run 1 - Output
Gained access! - 3
Gained access! - 2
Gained access! - 1
Gained access! - 4
23
Run 2 - Output
Gained access! - 1
Gained access! - 4
Gained access! - 3
Gained access! - 2
24
Run N - Output
Switching orders of Thread execution. Seen it hit a sum of 22.
Questions
I am attempting to do a simple Reentrant lock and syncrhonized practice.
Do these outputs indicate that ReentrantLock is using synchronized internally?
Are these locks/synchronized basically while loops until a variable is accessible or is execution actually paused (in bytecode) until Objects/Locks are unlocked?
Why isn't the sum always 24 in case above? The threads do the following:
Thread 1: Lock| 5s wait | value++
Thread 2: Lock| 0s wait | value++
Thread 3: syncronized | 5s wait | value++
Thread 4: syncronized | 0s wait | value++
4. Can someone confirm if this basically what synchronized is doing internally? My knowledge of the internal workings of synchronized is minimal. This is something I thought might be a logical way to replicate synchronized. So, again I am not sure if this is the right way. So please let me know if the internal workings in Java are different from this.
public class Driver {
static Safe<Integer> value = new Safe<Integer>(20);
public static void main(String [] arg) throws InterruptedException
{
Thread thr1 = new Thread(new Runnable(){
#Override
public void run() {
value.lock();
System.out.println("Gained access! - 1");
value.data++;
try {Thread.sleep(5000);} catch (InterruptedException e) {}
value.unlock();
}
});
Thread thr2 = new Thread(new Runnable(){
#Override
public void run() {
value.lock();
System.out.println("Gained access! - 2");
value.data++;
try {Thread.sleep(5000);} catch (InterruptedException e) {}
value.unlock();
}
});
thr1.start();
thr2.start();
thr1.join();
thr2.join();
System.out.println(value);
}
}
class Safe<E>{
private volatile boolean lock = false;
protected E data;
public Safe(E d)
{
data = d;
}
public String toString()
{
return data.toString();
}
public void lock()
{
while(isLocked()){}
lock = true;
}
public void unlock()
{
lock = false;
}
public boolean isLocked()
{
return lock;
}
}
Thank you!
They might, but this result does not say that. Why would you think that? Either way, the synchronized statement uses monitorenter and monitorexit, which use this (or an encoding thereof) as a conditional variable, which, in turn, is different from your ReentrantLock. The reason as to why the threads always execute in different order is simply that the execution order is up to the system scheduler. The order in which threads are queued for creation is generally not the order in which they run the first time.
If you trace down the Java framework code, you will find that eventually, Unsafe.park is called, whose implementation is system-dependent. That means, unless someone can produce an official Java document stating the implementation policies, we don't know if it uses "busy waiting" (loop until lock is available), wait-notify or a mixture of the two, and it might (and it probably does) vary between different systems and Java versions.
Your sum is not always correct because you have a race condition because synchronized and lock() are locking against different semaphores. Specifically, thread 1 and 2 are synchronized among each other, but not with 3 and 4. Because you have two synchronized increments, you will always see at least two increments (thus the sum is always at least 22).
/*
This should always produce 0 as output since all three methods increment(), decrement(), value() are thread safe(synchronized). but it is returning 1
*/
class Counter implements Runnable {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
public void run() {
try {
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
this.increment();
Thread.sleep(1000);
this.decrement();
Thread.sleep(1000);
}
catch (InterruptedException e){
return;
}
}
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
new Thread(c).start();
new Thread(c).start();
System.out.println(c.value());
}
}
like everyone else said you need to make sure that the treads have finished executing, to do that you need to call join. for example
public static void main(String args[]) throws InterruptedException {
Counter c = new Counter();
Thread t1 = new Thread(c).start();
Thread t2 = new Thread(c).start();
t1.join();
t2.join();
System.out.println(c.value());
}
that should run correctly
There's nothing to control when the main thread is calling value(). It will run as soon as it can acquire a lock on c, even though the other threads are still running.
If you want to wait until the threads are done, call join() on them.
You are reading the value before the threads have finished execution, so it may be well different from zero.
You're not waiting for the threads to complete running, so the result is that the value of c is printed at whatever it is at that second. I bet if you tried it 1000 times, there would be times when it wasn't 1.
IBM has a fair tutorial on the situation you're encountering:
http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=/rzahw/rzahwex3rx.htm