I am currently working on understanding the Java concept of multithreading. I went through a tutorial which uses the Tortoise and the Hare example to explain the concept of multithreading, and to a large extent I understood the syntax and the logic of the video tutorial. At the end of the video tutorial, the Youtuber gave an assignment that involves applying Multithreading to an olympic race track.
Using my knowledege from the example, I was able to create 10 threads (representing the athletes) that run within a loop, that executes 100 times (representing 100 meters).
My challenge is that when the Thread scheduler makes an Athlete to get to 100 meters before the other 9 athletes, the remaining 9 threads always do not complete their race. This is not usually the case in a standard race track. The fact that a Thread called Usain Bolts gets to 100 first, does not mean Yohan Blake should stop running if he is at 90m at that time.
I am also interested in getting the distance (note that they are all using the same variable) for each thread, so that I can use a function to return the positions of each Thread at the end of the race.
What I have done (that did not work):
1) I have tried to use an if else construct (containing nine "else"
statement) to assign the distance of each executing thread to a new integer variable. (using the Thread.currentThread().getName() property and the name of each thread) but that did not work well for me. This was an attempt to give positions to the athletes alone using their distance but does nothing about the 9 athletes not finishing the race.
2) I have also tried to use an ArrayList to populate the distance at runtime but for some strange reasons this still overwrites the distance each time it wants to add another distance.
Below are my codes:
package olympics100meters;
import java.util.ArrayList;
public class HundredMetersTrackRules implements Runnable {
public static String winner;
public void race() {
for (int distance=1;distance<=50;distance++) {
System.out.println("Distance covered by "+Thread.currentThread ().getName ()+" is "+distance+" meters.");
boolean isRaceWon=this.isRaceWon(distance);
if (isRaceWon) {
ArrayList<Integer> numbers = new ArrayList();
numbers.add(distance);
System.out.println("testing..."+numbers);
break;
}
}
}
private boolean isRaceWon(int totalDistanceCovered) {
boolean isRaceWon=false;
if ((HundredMetersTrackRules.winner==null)&& (totalDistanceCovered==50)) {
String winnerName=Thread.currentThread().getName();
HundredMetersTrackRules.winner=winnerName;
System.out.println("The winner is "+HundredMetersTrackRules.winner);
isRaceWon=true;
}
else if (HundredMetersTrackRules.winner==null) {
isRaceWon=false;
}
else if (HundredMetersTrackRules.winner!=null) {
isRaceWon=true;
}
return isRaceWon;
}
public void run() {
this.race();
}
}
This is my main method (I reduced it to 5 Athletes till I sort out the issues):
public class Olympics100Meters {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
HundredMetersTrackRules racer=new HundredMetersTrackRules();
Thread UsainBoltThread=new Thread(racer,"UsainBolt");
Thread TysonGayThread=new Thread (racer,"TysonGay");
Thread AsafaPowellThread=new Thread(racer,"AsafaPowell");
Thread YohanBlakeThread=new Thread (racer,"YohanBlake");
Thread JustinGatlinThread=new Thread (racer,"JustinGatlin");
UsainBoltThread.start();
TysonGayThread.start();
AsafaPowellThread.start();
YohanBlakeThread.start();
JustinGatlinThread.start();
}
}
My challenge is that ... the remaining 9 threads always do not complete their race.
This is caused by isRaceWon() method implementation. You check for it at each meter at each runner. As soon as the first runner achieves 100 meters, the break is called on next step of each runner loop (the race is won for every loop
btw, it makes sense to use volatile statuc String for winner's name, to avoid java's memory model ambiguities.
I am also interested in getting the distance ... for each thread, so that I can use a function to return the positions of each Thread at the end of the race.
If the final aim is to get the position, create a class field public List<String> finishingOrder = new ArrayList<String> and a method finish
private synchronized finish() {
finishingOrder.add(Thread.currentThread().getName())
}
and call it after the "run" loop
do not forget to call join() for all runner threads in your main. After that, the finishingOrder will contain names in order of finishing.
The code snippet below is causing isRaceWon to return true for every instance of HundredMetersTrackRules as soon as the shared winner field is set to non-null (i.e. someone wins.):
else if (HundredMetersTrackRules.winner!=null) {
isRaceWon=true;
}
This in turn causes the loop in race() to break for every instance of your Runnable. The run() method exits, terminating the thread.
The issue is just a logic error and not really specific to threading. But, as other posters have mentioned, there's some threading best-practices you can also adopt in this code, such as using volatile for fields shared by threads.
Actually For Race you need to start all the Threads at once then only its Race.
CountDownLatch is better one to Implement or write Race Program.
Many other way also we can write Race program without using the CountDownLatch.
If we need to implement using base / low level then we can use volatile boolean Flag and counter variable in synchronized blocks or using wait() and notifyAll() logic, etc.,
Introduced some time delay in your program inside the for loop. Then only you can feel the Experience. Why because you are not starting all the threads at once.
Hope you are Practicing Initial / base Level so I made few changes only for better understanding and Addressed all your queries.
import java.util.ArrayList;
import java.util.List;
import java.util.Collections;
class HundredMetersTrackRules implements Runnable {
public static Main main;
HundredMetersTrackRules(Main main){
this.main=main;
}
public static String winner;
public void race() {
try{
System.out.println(Thread.currentThread().getName()+" Waiting for others...");
while(!Main.start){
Thread.sleep(3);
}
for (int distance=1;distance<=50;distance++) {
System.out.println("Distance covered by "+Thread.currentThread().getName()+" is "+distance+" meters.");
Thread.sleep(1000);
}
synchronized(main){
Main.finish--;
}
Main.places.add(Thread.currentThread().getName());
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
public void run() {
this.race();
}
}
public class Main
{
public static volatile boolean start = false;
public static int finish = 5;
final static List<String> places =
Collections.synchronizedList(new ArrayList<String>());
public static void main(String[] args) {
HundredMetersTrackRules racer=new HundredMetersTrackRules(new Main());
Thread UsainBoltThread=new Thread(racer,"UsainBolt");
Thread TysonGayThread=new Thread (racer,"TysonGay");
Thread AsafaPowellThread=new Thread(racer,"AsafaPowell");
Thread YohanBlakeThread=new Thread (racer,"YohanBlake");
Thread JustinGatlinThread=new Thread (racer,"JustinGatlin");
UsainBoltThread.start();
TysonGayThread.start();
AsafaPowellThread.start();
YohanBlakeThread.start();
JustinGatlinThread.start();
Main.start=true;
while(Main.finish!=0){
try{
Thread.sleep(100);
}catch(InterruptedException ie){
ie.printStackTrace();
}
}
System.out.println("The winner is "+places.get(0));
System.out.println("All Places :"+places);
}
}
Related
I am trying to see how multithreading(particularly with synchronized keyword) works.In this example I want the second thread abc1 to start executing after thread abc. So I've used synchronized keyword in run function.But the output line which says:
Initial balance in this thread is 10000
Initial balance in this thread is 10000
is what concerns me.Because the initial balance should be "-243000" as indicated in output line
Final balance after intial -243000 is 59049000
because the abc1 thread should wait for abc due to synchronized keyword.
Primarily , I want the threads to behave as if I write
abc.start
abc.join()
abc1.start()
abc1.join()
Here is my source code:
class parallel extends Thread{
account a;
public parallel(account a) {
this.a=a;
}
public synchronized void run() {
synchronized(this) {
System.out.println("Initial balance in this thread is "+a.amount);
long duplicate=a.amount;
boolean flag=true;
//System.out.println("Transaction inititated");
for(int i=0;i<10;i++) {
if(flag==true) {
//System.out.println("Deducting "+amount+"Rs from your account");
a.amount-=a.amount*2;
}
else {
//System.out.println("Depositing "+amount+"Rs from your account");
a.amount+=a.amount*2;
}
flag=!flag;
}
System.out.println("Final balance after intial "+duplicate+" is "+a.amount);
syncro.amount=a.amount;
}
}
}
class account{
public account(long rupe) {
amount=rupe;
}
long amount;
}
public class syncro {
static long amount;
public static void main(String[] args) throws InterruptedException{
//for(int i=0;i<10;i++) {
account ramesh=new account(1000);
parallel abc=new parallel(ramesh);
parallel abc1=new parallel(ramesh);
abc.start();
//abc.join();
abc1.start();
//abc1.join();
//}
//awaitTermination();
//Thread.sleep(4000);
boolean ab=true;
long cd=1000;
for(int i=0;i<10;i++) {
if(ab==true) {
//System.out.println("Deducting "+ab+"Rs from your account");
cd-=cd*2;
}
else {
//System.out.println("Depositing "+a+"Rs from your account");
cd+=cd*2;
}
ab=!ab;
}
//System.out.println("Final amount by multithreading is "+);
System.out.println("Final amount after serial order is "+cd);
}
}
You are mixing the creating of your own threads with the use of synchronized. Also, using synchronized(this) within a synchronized method is doing the same thing twice.
Synchronized is NOT about starting threads. It is about allowing only one thread to enter a certain block of code at a time.
Every object you create has a hidden field that you cannot read, but it does exist. It is of type Thread and it is called owner.
The synchronized keyword interacts with this hidden field.
synchronized (object) {
code();
}
means the following:
If object.owner == Thread.currentThread(), then just keep going and increment a counter.
If object.owner == null, then run object.owner = Thread.currentThread(), set that counter to 1, and keep going.
Otherwise (So, object.owner is some other thread), stop, freeze the thread, and wait around until the owner is set to null, and then we can go to option #2 instead.
Once we're in, run code(). When we get to the closing brace, decrement the counter. If it is 0, run object.owner = null.
Furthermore, all the above is done atomically - it is not possible for 2 threads to get into a race condition doing all this stuff. For example, if 2 threads are waiting for owner to become unset again, only one will 'get it', and the other will continue waiting. (Which one gets it? A VM impl is free to choose whatever it wants; you should assume it is arbitrary but unfair. Don't write code that depends on a certain choice, in other words).
A method that is keyworded with synchronized is just syntax sugar for wrapping ALL the code inside it in synchronized(this) for instance methods and synchronized(MyClass.this) for static methods.
Note that synchronized therefore only interacts with other synchronized blocks, and only those blocks for which the object in the parentheses is the exact same obj reference, otherwise none of this does anything. It certainly doesn't start threads! All synchronized does is potentially pause threads.
In your code, you've put ALL the run code in one gigantic synchronized block, synchronizing on your thread instance. As a general rule, when you synchronize on anything, it's public API - other code can synchronize on the same thing and affect you. Just like we don't generally write public fields in java, you should not lock on public things, and this is usually public (as in, code you don't control can hold a reference to you). So don't do that unless you're willing to spec out in your docs how your locking behaviours are set up. Instead, make an internal private final field, call it lock, and use that (private final Object lock = new Object();).
I tried to create a race condition like this.
class Bankaccount {
private int balance=101;
public int getBalance(){
return balance;
}
public void withdraw(int i){
balance=balance-i;
System.out.println("..."+balance);
}
}
public class Job implements Runnable{
Bankaccount b=new Bankaccount();
public void run(){
if(b.getBalance()>100){
System.out.println("the balanced ammount is"+b.getBalance());
/*try{
Thread.sleep(9000);
}
catch(Exception e){
}*/
makeWithdrawl(100);
}
}
public void makeWithdrawl(int ammount){
b.withdraw(ammount);
System.out.println(b.getBalance());
}
public static void main(String[] args) {
Job x=new Job();
Job y=new Job();
Thread t1=new Thread(x);
Thread t2=new Thread(y);
t1.start();
t2.start();
}
}
I am getting output:
the balanced ammount is101
...1
1
the balanced ammount is101
...1
I was expecting it to be in negative as two times withdrawal happened for 100
What is missing here? Thanks in Advance
Race conditions appear when multiple threads change shared data. In your example each thread has its own Bankaccount class. You need to make it shared, like this:
class Job implements Runnable{
Bankaccount b;
Job(Bankaccount b){
this.b = b;
}
public void run(){
if (b != null)
if(b.getBalance()>100){
System.out.println("the balanced ammount is " + b.getBalance());
makeWithdrawal(100);
}
}
public void makeWithdrawal(int ammount){
b.withdraw(ammount);
System.out.println(b.getBalance());
}
public static void main(String[] args) {
// Creating one Bankaccount instance
Bankaccount b = new Bankaccount();
// Passing one instance to different threads
Job x=new Job(b);
Job y=new Job(b);
Thread t1=new Thread(x);
Thread t2=new Thread(y);
// Race conditions may appear
t1.start();
t2.start();
}
}
Unfortunately, this is not enough. Multithreaded programs are non deterministic and you can receive different results after several executions of the program. For example, thread t1 can manage to make withdrawal before thread t2 started to check the balance. Hence, t2 will not do withdrawal due to the lack of money.
To increase the likelihood of negative balance you can insert delay between checking the balance and withdrawing money.
There are several things you need to understand about this.
1) Your particular JVM on your particular system may be impervious to race conditions you are trying to reproduce here.
2) You are not likely to reproduce a race condition with a single run. It's supposed to be non-deterministic, if it gave consistent results it wouldn't be a race condition, but rather an error. To improve your chances make an automated sanity check and run the code 100k times.
3) Using memory barriers so that both threads start at the same time increases the chances a race condition will occur. Using a multi-core system helps too.
4) Your code cannot produce a race condition anyway. Look closely - each job is using it's own account. For a race condition you need shared state.
Your code cant create a race condition, but here is some information for you.
Reproducing a race condition reliably is going to be really hard to do because multi threaded programs are inherently non-deterministic. This means that there is no gaurunteed order to the order in which independent commands in independent threads execute.
This discussion has some good information on the topic:
Can a multi-threaded program ever be deterministic?
What I think you mean in your example, is that you want the balance to be garunteed to have a specific value after a thread executes on it. To do that, You will have to use locks to make sure the only one thread accesses the variable in question at a time.
A lock makes sure that any thread which attempts to read that value while some other thread is manipulating it, must wait until the thread manipulating the variable completes before it can then read and use the variable itself.
You will need locks to do what you are trying to do in your example
Here is the official documentation on using locks to protect
variables, it includes a small example
http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html
This Discussion has a good answer about utilizing locks
in java
Java Thread lock on synchronized blocks
try this code to generate a race condition
// This class exposes a publicly accessible counter
// to help demonstrate data race problem
class Counter {
public static long count = 0;
}
// This class implements Runnable interface
// Its run method increments the counter three times
class UseCounter implements Runnable {
public void increment() {
// increments the counter and prints the value
// of the counter shared between threads
Counter.count++;
System.out.print(Counter.count + " ");
}
public void run() {
increment();
increment();
increment();
}
}
// This class creates three threads
public class DataRace {
public static void main(String args[]) {
UseCounter c = new UseCounter();
Thread t1 = new Thread(c);
Thread t2 = new Thread(c);
Thread t3 = new Thread(c);
t1.start();
t2.start();
t3.start();
}
}
and try this code to fix it
public void increment() {
// increments the counter and prints the value
// of the counter shared between threads
synchronized(this){
Counter.count++;
System.out.print(Counter.count + " ");
}
}
this code snippet is from the book "Oracle Certified Professional Java SE 7 Programmer Exams 1Z0-804 and 1Z0-805" written by SG Ganesh, Tushar Sharma
I make two threads: one for fill an array and the second one print it. It seems like the two thread don't work in same time.
When i run the code its print first thread working then its print the array and second thread working how i can know if they working on same time or not?
here is my code:
public class Main {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
firstthread f=new firstthread();
secondthread s=new secondthread();
s.start();
f.start();
}
}
and the class the contain both fill and print method:
public class Array {
private static int [] ar=new int[500];
public static void fillarray()
{
for (int i = 0; i < ar.length; i++)
ar[i]=i;
}
public static void printarray()
{
for (int i = 0; i < ar.length; i++)
System.out.print(ar[i]+" ");
}
}
the first thread class:
public class firstthread extends Thread{
public void run() {
Array.fillarray();
System.out.print("first thread working ");
}
}
the second thread class:
public class secondthread extends Thread{
public void run() {
Array.printarray();
System.out.println("second array working");
}
}
The fillarray and printarray methods are running too fast so you aren't getting threading.
Add Thread.sleep(10) to each loop. That way the code will run much slower and the threads will intersperse. They will probably alternate with this approach.
Then change in to sleep a random # of seconds and you'll see different behavior.
You want an implementation of producer-consumer problem bro... Frankly speaking, without having a lock on the Object's monitor, you dont have control over anything. You dont have control over how much time a thread executes (Timeslice provided to it). If the time slice is too long, you will feel that one thread executes after another because your processor is so fast, your first thread will get ample time to finish its work . If you want to know how threads work exactly, use wait() and notify() and synchronized methods to change it into a producer-consumer problem.
Jeanne is also right, you can put sleep() , there's a 90 percent chance that it might work.
You could increase the number of elements being filled/printed.
There's a 70% chance of you reading more than what you wrote(filled in the array) if you dont use syncronized/wait/notify.
Starting a thread takes some time to the JVM. The first thread executes its run() method faster than the other thread is started. That's why you see that behavior.
Question isn't clear. Do you mean how can you tell if they are working on the same array? If that is the case the answer is Yes. the array is static meaning there would be only one of its kind which would belong to the class array. So there wont be multiple instances of it being worked on by the different threads.
As stated above, the threads run very fast. So even though they are accessing the same object, one thread would finish its job before the second even begins
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++;
}
}
}
I am fairly naive when it comes to the world of Java Threading and Concurrency. I am currently trying to learn. I made a simple example to try to figure out how concurrency works.
Here is my code:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadedService {
private ExecutorService exec;
/**
* #param delegate
* #param poolSize
*/
public ThreadedService(int poolSize) {
if (poolSize < 1) {
this.exec = Executors.newCachedThreadPool();
} else {
this.exec = Executors.newFixedThreadPool(poolSize);
}
}
public void add(final String str) {
exec.execute(new Runnable() {
public void run() {
System.out.println(str);
}
});
}
public static void main(String args[]) {
ThreadedService t = new ThreadedService(25);
for (int i = 0; i < 100; i++) {
t.add("ADD: " + i);
}
}
}
What do I need to do to make the code print out the numbers 0-99 in sequential order?
Thread pools are usually used for operations which do not need synchronization or are highly parallel.
Printing the numbers 0-99 sequentially is not a concurrent problem and requires threads to be synchronized to avoid printing out of order.
I recommend taking a look at the Java concurrency lesson to get an idea of concurrency in Java.
The idea of threads is not to do things sequentially.
You will need some shared state to coordinate. In the example, adding instance fields to your outer class will work in this example. Remove the parameter from add. Add a lock object and a counter. Grab the lock, increment print the number, increment the number, release the number.
The simplest solution to your problem is to use a ThreadPool size of 1. However, this isn't really the kind of problem one would use threads to solve.
To expand, if you create your executor with:
this.exec = Executors.newSingleThreadExecutor();
then your threads will all be scheduled and executed in the order they were submitted for execution. There are a few scenarios where this is a logical thing to do, but in most cases Threads are the wrong tool to use to solve this problem.
This kind of thing makes sense to do when you need to execute the task in a different thread -- perhaps it takes a long time to execute and you don't want to block a GUI thread -- but you don't need or don't want the submitted tasks to run at the same time.
The problem is by definition not suited to threads. Threads are run independently and there isn't really a way to predict which thread is run first.
If you want to change your code to run sequentially, change add to:
public void add(final String str) {
System.out.println(str);
}
You are not using threads (not your own at least) and everything happens sequentially.