So I'm new to this Thread stuff and I wrote a simple program to test avoiding Race Conditions. My first attempt was with Named Inner classes :
/* App1.java */
package ehsan;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class App1{
private final int poolSize = 10;
private final int numLoop = 5;
private int lastThread = 0;
public App1() {
ExecutorService taskList = Executors.newFixedThreadPool(poolSize);
for (int i = 0;i < poolSize;i++) {
taskList.execute(new Counter());
}
taskList.shutdown();
}
private class Counter implements Runnable{
#Override
public void run() {
synchronized (this) {
int currentThread = lastThread;
System.out.println("Current thread : "+currentThread);
lastThread = lastThread + 1;
}
System.out.println("Thread was executed");
}
}
}
and App1Test.java :
package ehsan;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
new App1();
}
}
So as a result it showed :
Current thread : 0
Thread was executed
Current thread : 1
Thread was executed
Current thread : 1
Thread was executed
Current thread : 3
Thread was executed
Current thread : 4
Thread was executed
Current thread : 5
Thread was executed
Current thread : 6
Thread was executed
Current thread : 7
Thread was executed
Current thread : 6
Current thread : 8
Thread was executed
Thread was executed
And whole things got mixed up and I'm facing Race conditions here even when I've use synchronized there.
But my second attempt worked! :
package ehsan;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class App1 implements Runnable{
private final int poolSize = 10;
private final int numLoop = 5;
private int lastThread = 0;
public App1() {
ExecutorService taskList = Executors.newFixedThreadPool(poolSize);
for (int i = 0;i < poolSize;i++) {
taskList.execute(this);
}
taskList.shutdown();
}
#Override
public void run() {
synchronized (this) {
int currentThread = lastThread;
System.out.println("Current thread : "+currentThread);
lastThread = lastThread + 1;
System.out.println("Thread was executed");
}
}
}
And the result was as I expected :
Current thread : 0
Thread was executed
Current thread : 1
Thread was executed
Current thread : 2
Thread was executed
Current thread : 3
Thread was executed
Current thread : 4
Thread was executed
Current thread : 5
Thread was executed
Current thread : 6
Thread was executed
Current thread : 7
Thread was executed
Current thread : 8
Thread was executed
Current thread : 9
Thread was executed
So my question is why my first attempt didn't work and the second one worked greatly? Thanks for helping me, I'm a beginner in Multi-Threaded programming!
In the first program, you create a different Counter instance as the Runnable whose run() method is executed by each thread, so synchronized (this) uses a different lock for each thread, and therefore the code is not thread safe. If you use the same Counter instance instead of creating a new one for each thread, this program will also behave as you expected.
Counter counter = new Counter();
for (int i = 0;i < poolSize;i++) {
taskList.execute(counter);
}
In the second program, you use the same App1 instance as the Runnable whose run() method is executed by all the threads, so synchronized (this) uses the same locks for all the threads.
With a great deal of research I found few ways to solve this.
Please Note : Some of these solutions were pointed out by Eran, Thomas and etc. and I thank them for helping me but I just wanted to collect all the possible solutions in a single answer so the future visitors of this post find the answers easily.
For Named Inner Classes :
Instead of using this as the locking object for synchronization we can use the OutterClass instance :
synchronized (App1.this) {
int currentThread = lastThread;
System.out.println("Current thread : "+currentThread);
lastThread = lastThread + 1;
}
For Separated Classes :
Solution 1
Synchronizing on an object we are receiving from the Caller Class( The class containing the task list and ... ). Here is an example :
public App1 implements Runnable {
private final Integer shared;/* Not spending time on auto-boxing */
public App1(Integer sharedNum) {
shared = sharedNum;
}
#Override
public void run() {
synchronization(shared){
//code here
}
}
}
public App1Test {
private final int forSharing = 14;
public static void main(String[] args) {
ExecutorService taskList = Executors.newFixedThreadPool(poolSize);
taskList.execute(new App1(forSharing));
// and lob lob
}
}
Solution 2
Synchronization on class object :
synchronized (App1.class) { /* As the fields and methods of class App1 are the same for all objects */
int currentThread = lastThread;
System.out.println("Current thread : "+currentThread);
lastThread = lastThread + 1;
}
Solution 3
Synchronizing on an static field ( Which I loved it because its really innovative ) :
/* Add this field to class definition */
private static Object sharedObject = new Object();
/* Now in `run` method use the object like this : */
synchronized(sharedObject) {
//TODO : write your code here :)
}
So these are the solutions to this sneaky problem which is a bit hard to debug :)
I hope this helps fellows who have faced the same problem :)
Cheers, Ehsan
synchronized (this) in Counter synchronizes on the instance, so if you pass a new instance to each thread (taskList.execute(new Counter());) there won't be any synchronization at all (since no 2 threads use the same instance to synchronize on). Thus either use synchronized(Counter.class) or some other shared monitor object (since Counter is an inner class of App1 you could use synchronize(App1.this)).
Your second approach works since you pass the same instance to each thread: taskList.execute(this);.
Related
Can someone help me to solve this multi-threading problem ?
The program should initiate three threads with a common resource. Each thread should print a incremented count value. Sample output is mentioned below. where T1,T2 and T3 are threads.
T1 T2 T3
1 2 3
4 5 6
7 8 9
My current code:
public class RunnableSample implements Runnable {
static int count = 0;
public void run() {
synchronized (this) {
count++;
System.out.println(
"Current thread : Thread name :" + Thread.currentThread().getName()
+ " Counter value :" + count
);
}
}
}
//main method with for loop for switching between the threads
public class ThreadInitiator {
public static void main(String[] args) {
RunnableSample runnableSample = new RunnableSample();
Thread thread1 = new Thread(runnableSample, "T1");
Thread thread2 = new Thread(runnableSample, "T2");
Thread thread3 = new Thread(runnableSample, "T3");
for (int i = 0; i < 9; i++) {
thread1.start();
thread2.start();
thread3.start();
}
}
}
Create a synchronized method to increment the value. When a method is identified as synchronized, only one thread can access it at a time and the other threads wait for the initial thread to complete method execution before they can access the method.
Pls check How to synchronize a static variable among threads running different instances of a class in java?
This question already has an answer here:
Thread not returning after notifyall()
(1 answer)
Closed 7 years ago.
I am trying to create two threads to act as counters. When one thread decrements its counter, it should toggle the value of the shared boolean flag field, call the notifyAll() method and release the other thread from the wait() method being called. The logic field serves as a means to avoid deadlock, i.e. one thread will call the wait() method when the flag field has a value of true, the other thread will call it when the flag field has a value of false. You can see the way I run the threads created from this class, as well as the expected output below. The problem is that both threads get stuck on the wait() method at the same time and only the first line of output goes through.
The expected output:
Thread No.1 4
Thread No.2 4
Thread No.1 3
Thread No.2 3
Thread No.1 2
Thread No.2 2
Thread No.1 1
Thread No.2 1
Thread No.1 0
Thread No.2 0
The actual output:
Thread No.2 4
The counter class:
public class CounterThread implements Runnable {
private long counter;
private static int threadNumber = 0;
private int index = 0;
private static boolean flag = true;
private boolean logic;
public CounterThread(long counter, boolean logic) {
index = ++threadNumber;
this.counter = counter;
this.logic = logic;
}
private synchronized void toggleFlag() {
flag = !flag;
notifyAll();
}
#Override
public synchronized void run() {
while (counter > 0) {
while (flag==logic) {
try {
wait();
} catch (InterruptedException e) {
}
}
counter--;
System.out.println("Thread No. " + index + " " +counter);
toggleFlag();
}
}
}
The way I run it:
public final class CounterThreadRun {
public static void main(String[] args) {
CounterThread counter1 = new CounterThread(5, true);
CounterThread counter2 = new CounterThread(5, false);
Thread thread1 = new Thread(counter1);
Thread thread2 = new Thread(counter2);
thread1.start();
thread2.start();
}
}
Because you're not notifying the thread that is waiting. You're only notifying the current thread, i.e. yourself. You need a shared object, perhaps a static in the class, that is used for both wait() and notifyAll().
This is some sort of a Java Puzzler, that I stumbled across and can't really explain. Maybe somebody can?
The following program hangs after a short time. Sometimes after 2 outputs, sometimes after 80, but almost always before terminating correctly. You might have to run it a few times, if it doesn't happen the first time.
public class Main {
public static void main(String[] args) {
final WorkerThread[] threads = new WorkerThread[]{ new WorkerThread("Ping!"), new WorkerThread("Pong!") };
threads[0].start();
threads[1].start();
Runnable work = new Runnable() {
private int counter = 0;
public void run() {
System.out.println(counter + " : " + Thread.currentThread().getName());
threads[counter++ % 2].setWork(this);
if (counter == 100) {
System.exit(1);
}
}
};
work.run();
}
}
class WorkerThread extends Thread {
private Runnable workToDo;
public WorkerThread(String name) {
super(name);
}
#Override
public void run() {
while (true){
if (workToDo != null) {
workToDo.run();
workToDo = null;
}
}
}
public void setWork(Runnable newWork) {
this.workToDo = newWork;
}
}
Now, it's clear that busy waiting loops are not a great idea in general. But this not about improving, it's about understanding what is happening.
Since everything works as expected when WorkerThread.setWork() is synchronized or when the WorkerThread.workToDo field is set to volatile I suspect a memory issue.
But why exactly is it happening? Debugging doesn't help, once you start stepping through, everything behaves as expected.
An explanation would be appreciated.
The first problem is that you are setting the Runnable workToDo from the main thread and then reading it in the 2 forked threads without synchronization. Any time you modify a field in multiple threads, it should be marked as volatile or someone synchronized.
private volatile Runnable workToDo;
Also, because multiple threads are doing counter++ this also needs to be synchronized. I recommend an AtomicInteger for that.
private AtomicInteger counter = new AtomicInteger(0);
...
threads[counter.incrementAndGet() % 2].setWork(this);
But I think the real problem may be one of race conditions. It is possible for both threads to set the workToDo to be the Runnable and then have them both return and set it back to be null so they will just spin forever. I'm not sure how to fix that.
1. threads[0] has it's `workToDo` set to the runnable. It calls `run()`.
2. at the same time threads[1] also calls `run()`.
3. threads[0] sets the `workToDo` on itself and threads[1] to be the runnable.
4. at the same time threads[1] does the same thing.
5. threads[0] returns from the `run()` method and sets `workToDo` to be `null`.
6. threads[1] returns from the `run()` method and sets `workToDo` to be `null`.
7. They spin forever...
And, as you mention, the spin loop is crazy but I assume this is a demonstration thread program.
The problem occurs right between these lines:
workToDo.run();
workToDo = null;
Suppose the following sequence of events occurs:
- Original Runnable runs. "Ping!".setWork() called
- Ping! thread realizes workToDo != null, calls run(), the stops between those two lines
- "Pong!".setWork() called
- Pong! thread realizes workToDo != null, calls run()
- "Ping!".setWork() called
- Ping! thread resumes, sets workToDo = null, ignorantly discarding the new value
- Both threads now have workToDo = null, and the counter is frozen at 2,...,80
Program hangs
my 2 cents....
import java.util.concurrent.atomic.AtomicReference;
class WorkerThread extends Thread {
private AtomicReference<Runnable> work;
public WorkerThread(String name) {
super(name);
work = new AtomicReference<Runnable>();
}
#Override
public void run() {
while (true){
Runnable workToDo = work.getAndSet(null);
if ( workToDo != null ) {
workToDo.run();
}
}
}
public void setWork(Runnable newWork) {
this.work.set(newWork);
}
}
I am learning about MULTITHREADING in java and I want to know why in the following code, the child thread does not immediately run when the start method is executed to invoke the run method in the child thread?
Instead, after executing the start method, the main thread keeps executing its code and starts printing ".". Which it does three times and the control is taken over by the child thread. The child thread then executes its code one time and returns back to the main thread. Then main thread completes and then the child thread completes its execution as well.
I am unable to understand why this happens?
class MyThread implements Runnable {
String thrdName;
MyThread(String name) {
thrdName = name;
}
public void run() {
System.out.println(thrdName + " starting.");
for (int count = 0; count < 10; count++) {
System.out.println("In " + thrdName + ", count is " + count);
}
}
}
class UseThreads {
public static void main(String args[]) {
System.out.println("Main thread starting.");
MyThread mt = new MyThread("Child #1");
Thread newThrd = new Thread(mt);
newThrd.start();
for (int i = 0; i < 50; i++) {
System.out.print(".");
}
}
}
When you call start() on your thread, you get no guarantees on how fast it will start. This is up to the thread scheduler of your computer. If you run your code multiple times, you will likely get several different execution orders for your threads.
The call to begin a thread is asychronous. It does not wait until the thread has started running before returning; it returns essentially immediately.
You can implement that behaviour yourself, with a bit of locking, such that your main thread pauses until the thread you have begun issues a signal of some kind, to indicate it has begun execution.
I have a java application where the main-thread starts 2 other threads.
If one of these threads terminates, the main-thread may start another thread depending on the result of the terminated thread.
Example:
The main-thread creates 2 threads: A and B. Thread A will load a picture and thread B will load another picture. If A terminates and loaded the picture successfully a new Thread C will be created which does some other stuff and so on.
How can i do this? I do not want to use busy waiting in the main thread and check every 100ms if one of the two threads has finished.
I think i cannot use a thread pool because the number of active threads (in this case A and B) will vary extremely and it's the main-threads dicision to create a new thread or not.
This is rough sketch of the "busy waiting" solution:
public class TestThreads {
private class MyThread extends Thread {
volatile boolean done = false;
int steps;
#Override
public void run() {
for (int i=0; i<steps; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException exc) { }
}
done = true;
synchronized (this) {
notify();
}
}
public void waitFor(long ms) {
synchronized (this) {
try {
wait(ms);
} catch (InterruptedException exc) { }
}
}
}
public void startTest() {
MyThread a = new MyThread();
a.steps = 6;
a.start();
MyThread b = new MyThread();
b.steps = 3;
b.start();
while (true) {
if (!a.done) {
a.waitFor(100);
if (a.done) {
System.out.println("C will be started, because A is done.");
}
}
if (!b.done) {
b.waitFor(100);
if (b.done) {
System.out.println("C will be started, because B is done.");
}
}
if (a.done && b.done) {
break;
}
}
}
public static void main(String[] args) {
TestThreads test = new TestThreads();
test.startTest();
}
}
This sounds like a classic case for using a ThreadPoolExecutor for performing the tasks concurrently, and wrapping it with an ExecutorCompletionService, for collecting the results as they arrive.
For example, assuming that tasks contains a set of tasks to execute in parallel, each returning a String value when it terminates, the code to process the results as they become available can be something like:
List<Callable<String>> tasks = ....;
Executor ex = Executors.newFixedThreadPool(10);
ExecutorCompletionService<String> ecs = new ExecutorCompletionService<String>(ex);
for (Callable<String> task : tasks)
ecs.submit(task);
for(int i = 0; i < tasks.size(); i++) {
String result = ecs.take().get();
//Do something with result
}
If you include the identity of the task as a part of the returned value, then you can make decisions depending on the completion order.
Check Semaphore
A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acquire() blocks if necessary until a permit is available, and then takes it
So, whenever you thread finishes, it frees one permit, which is then acquired by the main thread
You should use a thread pool. In a thread pool, you have a fixed number of threads and tasks are kept in a queue; whenever a thread is available, a task is taken off the queue and executed by that thread.
Here is a link to the Sun tutorial on thread pooling.
Edit: just noticed that you wrote in your answer that you think you cannot use thread pooling. I don't see why this is the case. You can set threads to be created on-demand rather than all at once if you are worried about creation overhead, and once created an idle thread is not really going to hurt anything.
You also say that it's the main thread's decision to create a new Thread or not, but does it really need to be? I think that may just overcomplicate things for you.
Is there a reason to control the thread execution directly instead of using something like
ExecutorService?
#danben got there first, but I fell into the same pooling trap.
A lot of the complexity in your code is that the main thread is trying to wait on two different objects. There's nothing which says you can't use wait and notify on another object, and if your tasks are ( A or B ) then C, the code below will work - wait on a reference which is set to indicate the first task to complete.
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public class BiggieThreads
{
private static class MyTask implements Runnable
{
final int steps;
final AtomicReference<MyTask> shared;
final String name;
MyTask ( int steps, AtomicReference<MyTask> shared, String name )
{
this.shared = shared;
this.steps = steps;
this.name = name;
}
#Override
public void run()
{
for ( int i = 1; i <= steps; i++ ) {
System.out.println ( "Running: " + this + " " + i + "/" + steps);
try {
Thread.sleep ( 100 );
} catch ( InterruptedException exc ) { }
}
// notify if this is the first to complete
if ( shared.compareAndSet ( null, this ) )
synchronized ( shared ) {
shared.notify();
}
System.out.println ( "Completed: " + this );
}
#Override
public String toString ()
{
return name;
}
}
public void startTest() throws InterruptedException
{
final ExecutorService pool = Executors.newFixedThreadPool ( 3 );
final AtomicReference<MyTask> shared = new AtomicReference<MyTask>();
Random random = new Random();
synchronized ( shared ) {
// tasks launched while lock on shared held to prevent
// them notifying before this thread waits
pool.execute ( new MyTask ( random.nextInt ( 5 ) + 3, shared, "a" ) );
pool.execute ( new MyTask ( random.nextInt ( 5 ) + 3, shared, "b" ) );
shared.wait();
}
System.out.println ( "Reported: " + shared.get() );
pool.shutdown();
}
public static void main ( String[] args ) throws InterruptedException
{
BiggieThreads test = new BiggieThreads ();
test.startTest();
}
}
I'd tend to use a semaphore for this job in production, as although the wait is quite simple, using in semaphore puts a name to the behaviour, so there's less to work out when you next read the code.