Why is synchronization not working properly within this code? - java

Over the past few days I have been reading articles about Multithreading and I have come across a simple task using multhithreading. This is the task:
Create an application which simulates the running race of 50 meters(in my code they are 10, does not matter). The number of runners should be 5 and you should name each runner thread. Print the winner. All the other threads should complete the race, as well. Print the time taken by each runner to complete the race and highlight the winner's time.
This is the code I've written:
public class Racer implements Runnable {
public static String winner;
public static int time = 0;
public void incrementTime() {
synchronized (Racer.class) {
time++;
}
}
public void race() {
for (int distance = 1; distance <= 10; distance++) {
incrementTime();
System.out.println("Distance covered by " + Thread.currentThread().getName() + " is " + distance + " meters.");
boolean finalDest = this.isTheRaceOver(distance);
if (finalDest) {
break;
}
}
}
private boolean isTheRaceOver(int finalDistance) {
boolean isRaceOver = false;
if (Racer.winner == null && finalDistance == 10) {
String winnerName = Thread.currentThread().getName();
Racer.winner = winnerName;
System.out.println("The winner is : " + Racer.winner + " with time " + time);
isRaceOver = true;
} else if (Racer.winner == null) {
isRaceOver = false;
} else if (finalDistance != 10) {
isRaceOver = false;
} else if (finalDistance == 10) {
System.out.println(Thread.currentThread().getName() + " is with time " + time);
}
return isRaceOver;
}
#Override
public void run() {
this.race();
}
}
public class RacerDemo {
public static void main(String[] args) {
Racer racer = new Racer();
Thread a = new Thread(racer, "A");
Thread b = new Thread(racer, "B");
Thread c = new Thread(racer, "C");
Thread d = new Thread(racer, "D");
Thread e = new Thread(racer, "E");
a.start();
b.start();
c.start();
d.start();
e.start();
}
}
One output is:
Distance covered by A is 1 meters.
Distance covered by C is 1 meters.
Distance covered by C is 2 meters.
Distance covered by C is 3 meters.
Distance covered by C is 4 meters.
Distance covered by C is 5 meters.
Distance covered by C is 6 meters.
Distance covered by C is 7 meters.
Distance covered by C is 8 meters.
Distance covered by C is 9 meters.
Distance covered by C is 10 meters.
The winner is : C with time 12 // should be 11 ?
Distance covered by B is 1 meters.
Distance covered by B is 2 meters.
...... and so on
The thing that bothers me is when it prints the time taken by each racer(thread) to cover the distance, it does not show the right time. I made incrementTime() synchronized, but the program does not work properly either. Can you tell me what is wrong? Where is my mistake?

Each runner increments the time, causing an inconsistent state. You should separate the racers from the actual race, which should probably be in a separate class.
Your problem occurs in the race method of the Racer Runnable, where each runner increments the static time field, thus causing the unexpected behavior.

In your implementation, time is shared by all the threads. So, if one thread increments is, the other thread will read that value, e.g.:
Thread 1 enters race() value of time is 0
Thread 1 calls incrementTime() changing the value to 1
Thread 2 enters race() value of time is 1
Thread 2 calls incrementTime() changing the value to 2
This will leave the time variable in an inconsistent state. To avoid this, you can try delaring time inside race() method so that each thread has its own time.

Every runner increments time and there is only a lock on the increments time method. Runner C finishes their race and calls the isRaceOver method. As c is going to get the time of 11, thread b runs the race method, sneaks in and increments time 1. As a result, c gets the time of 12 and prints out the time incorrectly. If your intention is for all runners to be able to increment the time, you have to make sure that only 1 thread is running race or IsTheRaceOver at a time.

You would get same result without synchronized block since you synchronized an integer which is atomic by default. Synchronized keyword is unnecessary so there is no synchronization at all.
Distance covered by A is 1 meters.
Distance covered by C is 1 meters.
Distance covered by C is 2 meters.
...
The winner is : C with time 12 // should be 11 ?
From your output it's clear that another thread was incremented time too. There might be another thread which incremented time right before you print the winner. To solve your problem, you have to synchronize both incrementTime and isTheRaceOver methods this way you will make sure another thread will not be able to increment time right before you print it.
But hold on: Synchronized block does not guarantee updates are visible to another threads which is called cache coherence. If you don't use volatile keywords when one thread updates a variable, it's not guaranteed that another thread will see it. For example even if you set the winner another thread may still see it as null.
Make sure you use volatile keyword or locks (which also use memory barriers) to guarantee that the updates will be visible to other threads.

Related

How to "queue" the same thread?

I'm building a elevator simulator using sliders. I need the "elevators" to move at the same time, so I thought of using threads, but my knowledge is basic on this topic. ;) I got the elevators to move via threads (see code below) but I'm stuck on the option to move a specific elevator to one floor (e.g. from floor 4 to floor 10) AND THEREAFTER TO ANOTHER FLOOR (e.g. floor 1) If I just create the threads, the elevator tries to move in both directions simultaneously! So I tried to check if the thread name existed already, and then it will only move in one direction. Problem is that it then ignores the second command to move in the other direction. I assume that it has to do with the fact that the thread name still exists, or maybe that the code execution has moved past the second 'command' to move to floor 1? Please help!
private void btnResetActionPerformed(java.awt.event.ActionEvent evt) {
moveLift(1, 10); //moves lift 1 to floor 10
moveLift(1, 1); //should move lift 1 to floor 1 from 10
moveLift(2, 10); //moves lift 2 to floor 10
}
private void moveLift(int liftNum, int floorNum) {
boolean b = false;
Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread t : threads) {
String name = t.getName();
if (name.equals("Lift" + liftNum)) {
b = true;
}
}
if (!b) {
MyThread mt = new MyThread(liftNum, floorNum);
mt.setName("Lift" + liftNum);
mt.start();
}
}
Any advise on queuing the moveLift commands so the threads don't fight each other?

Who can explain the result?

public class Bank {
private int sum=0;
public void add(int n) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
sum+= n;
System.out.println(sum);
}
}
public class Consumer implements Runnable {
Bank bank = new Bank();
#Override
public void run() {
for (int i = 0; i < 10; i++) {
bank.add(100);
}
}
}
public class Tes2 {
public static void main(String[] args) {
Consumer consumer = new Consumer();
Thread thread1 = new Thread(consumer);
Thread thread2 = new Thread(consumer);
thread1.start();
thread2.start();
}
}
This is a multithreaded program, simulation is multiple depositors to the bank to deposit money, used to demonstrate multithreaded security issues.Since the code is not synchronized, its first and second results might be 200/200,200/300, and so on.But I don't understand why you get 100/100, who can explain?
This is a race condition.
Both threads have access to sum.
sum += n; is not atomic
Thread 1 reads sum 0
Thread 2 swaps in because the code isnt synchronized reads sum as 0
Thread 1 adds 100 to 0 and writes that to sum
Thread 2 adds 100 to 0 and writes that to sum overwriting thread 1s value
If you think about the concurrency of this program just based on the lines in the code, the 100/100 output result wouldn't make sense. But you also have to think about what instructions are actually happening when these lines are being performed. Each line of code can consist of many, many assembly instructions. In this case, to add n to sum, what really happens is that the value of sum is read from memory, probably loaded onto a register, incremented, then re-written onto memory.
The 100/100 output can happen in the following scenario. Let's say thread 1 and thread 2 both call bank.add(100), and the bank handles requests asynchronously. That is, the bank has a thread handling each request.
Then, thread 1 of the bank loads the value of sum, which is zero. Thread 2 also loads the value of sum right after, which is still zero. Then, thread 1 takes the value it loaded, adds n=100, and writes it into memory. Thread 2 does the same; it takes the value of sum it loaded previously, 0, adds 100, then writes it back onto memory. Then, they each print out the value of 100.

How to avoid threads to starve

Suppose I have a hotel with m Rooms.
Guests (Threads) come in and out the whole time.
A Room can have lots of people inside, but only one Room will have people. For example:
Guest A (wants Room 1)
Guest B (wants Room 2)
Guest C (wants Room 1)
A can go to Room 1, once all rooms are empty;
B cannot go to Room 2 yet, given that there is another room with people still inside;
C can go to Room 1, because the Room C wants is the only Room with people inside;
Given that A and C leave Room 1, B should be able to go to Room 2
The last Guest to exit a room should stop every other Guests (avoiding them to come in while he is coming out) until it leaves, so the others can continue
How can I implement this somehow the threads will not starve?
For simplicity, suppose that, once the Guest comes inside a room, it sleeps for some seconds and then get out. Here is my (wrong) implementation:
import java.util.ArrayList;
import java.util.Random;
public class Guest extends Thread {
static Rooms rooms = new Rooms(5);
int id;
Guest(int id) {
this.id = id;
}
public void run() {
rooms.join(this);
nap();
rooms.quit(this);
}
public void nap() {
try {
sleep((new Random().nextInt(4000) + 1000));
} catch (InterruptedException e) {
}
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 20; i++) {
Thread t = new Guest(i);
t.start();
Thread.sleep((long) new Random().nextInt(1500) + 1000);
}
}
}
class Rooms {
Room[] rooms;
int busy;
Rooms(int m) {
busy = -1;
rooms = new Room[m + 1];
for (int i = 0; i < m + 1; i++)
rooms[i] = new Room();
}
void join(Guest h) {
if (busy == -1) {
busy = (new Random().nextInt(rooms.length));
}
rooms[busy].add(h);
System.out.println("Guest " + h.id + " came inside room " + busy + " with " + rooms[busy].size() + " people");
}
void quit(Guest h) {
if (rooms[busy].size() == 1) {
setHandler(busy, h);
} else {
rooms[busy].remove(h);
System.out
.println("Guest " + h.id + " came out of room " + busy + " with " + rooms[busy].size() + " people");
}
}
synchronized void setHandler(int numQuarto, Guest ultimo) {
System.out.println("(Last) Guest " + ultimo.id + " came out of room " + busy + " with "
+ rooms[numQuarto].size() + " people");
rooms[numQuarto].remove(ultimo);
busy = -1;
}
}
class Room extends ArrayList<Guest> {
}
To do this with threads -- which is highly artificial, but I suppose it is an exercise -- you need to learn how to make a Thread wait on a condition, and how to notify one or more Threads that the condition they are waiting for may have been satisfied. Conveniently, every object has methods wait(), notify(), and notifyAll() that serve these purposes.
One important consideration with wait / notify is that you must be careful to wait on and notify the correct object. Generally, that's not the Thread you want to be affected, but rather some shared object that all threads involved rely upon for mutual synchronization. In this particular case, it looks like Guest.rooms would do nicely.
The general idea would be that in Rooms.join(), the current thread tests whether it can immediately take a room. If so, it does, and continues as now. If not, however, it invokes wait() (on the Rooms instance, which at that point is this). Whenever that wait() returns, the thread must again check whether it can immediately take the room it wants; if not, it must wait again.
The other half would be in Rooms.quit(). Whenever a thread running that method is the last one out of the room, it must reset busy to indicate that no room is occupied, and then, importantly, invoke notifyAll() to let all threads waiting at that time know that there's a chance to get a room.
You will find that you need to employ proper synchronization for this. In particular, you can invoke wait() and notifyAll() (and notify()) only while holding the monitor of the target object (it will be released for the duration of the wait, and reacquired before wait() returns). You will also need to ensure that you properly synchronize all manipulation of shared objects, however, in this case mainly the Rooms and its members, without preventing threads from proceeding when otherwise they could. In particular, be aware that threads that sleep() do not for that reason release any monitors they may hold.
The rest is up to you. I've given you rather a lot more of a hint than maybe I should, but it truly is a bit tricky to learn how to use wait / notify properly.
You can't. Based on what you've given, other mechanisms would need to be implemented which guarantee no starvation can occur. For example,
Guests (Threads) come in and out the whole time.
So, it's possible that n threads come in for Room m possibly the whole time. It's possible, too, that during that time more threads come in wanting another room. However, they cannot access the room until Room m is first emptied (which may never actually happen). This can continue for any number of rooms and threads. This is the case even if...
For simplicity, suppose that, once the Guest comes inside a room, it
sleeps for some seconds and then get out.
And that's because...
C can go to Room 1, because the Room C wants is the only Room with
people inside;
Which implies that another thread may enter an already occupied room with one or more threads with t time left to sleep. The new thread goes to sleep and won't wake up until after the previous one. While sleeping n more threads may enter the room potentially causing other threads waiting for other rooms to starve.

Unexpected result in multithreaded program

This simple program has a shared array and 2 threads:
first thread - shows sum of values in the array.
second thread - subtracts 200 from one cell of the array and adds 200 to another cell.
I would expect to see the results: 1500 (sum of the array), 1300 (if the display occurs between the subtraction and the addition).
But for some reason, sometimes 1100 and 1700 appear, which I can't explain...
public class MainClass {
public static void main(String[] args) {
Bank bank = new Bank();
bank.CurrentSum.start();
bank.TransferMoney.start();
}
}
class Bank {
private int[] Accounts = { 100, 200, 300, 400, 500 };
private Random rnd = new Random();
Thread CurrentSum = new Thread("Show sum") {
public void run() {
for (int i = 0; i < 500; i++) {
System.out.println(Accounts[0] + Accounts[1] + Accounts[2]
+ Accounts[3] + Accounts[4]);
}
}
};
Thread TransferMoney = new Thread("Tranfer"){
public void run(){
for(int i=0; i<50000; i++)
{
Accounts[rnd.nextInt(5)]-=200;
Accounts[rnd.nextInt(5)]+=200;
}
}
};
}
You are not updating the values in an atomic or thread safe manner. This means sometimes you see two more -200 than +200 and sometimes you see two more +200 than -200. As you iterate over the values it is possible to see a +200 value but the -200 value is an earlier value and you miss it, but you see another +200 update again missing the -200 change.
It should be possible to see up to 5 x +200 or 5 x -200 in rare cases.
It's happening because the addition of the five values is not atomic, and may be interrupted by the decrement and increment happening in the other thread.
Here's a possible case.
The display thread adds Accounts[0]+Accounts[1]+Accounts[2].
The updating thread decrements Accounts[0] and increments Accounts[3].
The updating thread decrements Accounts[1] and increments Accounts[4].
The display thread continues with its addition, adding Accounts[3] and Accounts[4] to the sum that it had already partially evaluated.
In this case, the sum will be 1900, because you've included two values after they've been incremented.
You should be able to work out cases like this, to give you sums of anything between 700 and 2300.
Perhaps on purpose, you are not doing the addition operation atomically.
That means that this line:
System.out.println(Accounts[0] + Accounts[1] + Accounts[2]
+ Accounts[3] + Accounts[4]);
Will run in multiple steps, any of which can occur during any iteration of the second thread.
1. Get value of Accounts[0] = a
2. Get value of Accounts[1] = b
...So on
The addition then happens after all the values are pulled from the array.
You can imagine that 200 is subtracted from Accounts[0], which is dereferenced by the JRE, then in another loop of the second thread, 200 is removed from Accounts[1], which is subsequently dereferenced by the JRE. This can result in the the output you see.
The Accounts variable is being accessed from more than one thread, one of which modifies its value. In order for the other thread to reliably read the modified values at all it is necessary to use a "memory barrier". Java has a number of ways of providing a memory barrier: synchronized, volatile or one of the Atomic types are the most common.
The Bank class also has some logic which requires the modifications to be made in multiple steps before the Accounts variable is back in a consistent state. The synchronized keyword can also be used to prevent another block of code that is synchronised on the same object from running until the first synchronized block has completed.
This implementation of the Bank class locks all access to the Accounts variable using the mutex lock object of the Bank object that owns the Accounts variable. This ensures that each synchronised block is run in its entirety before the other thread can run its own synchronised block. It also ensures that changes to the Accounts variable are visible to the other thread:
class Bank {
private int[] Accounts = { 100, 200, 300, 400, 500 };
private Random rnd = new Random();
Thread CurrentSum = new Thread("Show sum") {
public void run() {
for (int i = 0; i < 500; i++) {
printAccountsTotal();
}
}
};
Thread TransferMoney = new Thread("Tranfer"){
public void run(){
for(int i=0; i<50000; i++)
{
updateAccounts();
}
}
};
synchronized void printAccountsTotal() {
System.out.println(Accounts[0] + Accounts[1] + Accounts[2]
+ Accounts[3] + Accounts[4]);
}
synchronized void updateAccounts() {
Accounts[rnd.nextInt(5)]-=200;
Accounts[rnd.nextInt(5)]+=200;
}
}

set a delay in libgdx game

i have a game(like super jumper, this game is a jumping game) that our character has life. after collision with enemies, his life reduce. and i want to after 1 sec , calculate the collisions. i mean in this 1 sec, if my character contact with enemies , nothing happen and he continue his way.
for this , i define a boolean variable in my GameScreen class, name "collision" and another in Wolrd class, name "collBirds". after one contact with enemy collision and collBirds change to true. but i want after 1 sec collistion change to false. i use several things like System.currentTimeMillis() and "for loop",and nothing happen. i'm not so good in java.
this is my condition:
if(World.collBirds == true && collition == false){
life -= 1;
lifeString = "Life : " + life;
World.collBirds = false;
collition = true;
for (??? "need to stay here for 1 sec" ???) {
collition = false;
}
}
In some cases you could also want to use com.badlogic.gdx.utils.Timer
Example usage:
float delay = 1; // seconds
Timer.schedule(new Task(){
#Override
public void run() {
// Do your work
}
}, delay);
When the first collision occurs, set a float timeSinceCollision = 0;
Then each loop, you will need to add the time since last check to the variable, and check if it's more than a second.
timeSinceCollision += deltaTime;
if(timeSinceCollision > 1.0f) {
// do collision stuff
} else {
// ignore the collision
}
If you want to do this in same thread than you can use Thread.sleep(). But in this case your current thread will freeze and if this is single thread game, than your whole game will freeze. If you don't want your game to freeze for 1 second, than you should spawn the thread and in that thread call the sleep and after sleep, change the flag

Categories