Something wrong with the Peterson algorithm logic? - java

I am pretty new to Multithreading programming. In my code threads are trying to acquire locks around few lines. The lines work pretty fine for few context switches but then it halts (probably a deadlock).
On the other hand if use synchronized block then all works fine.
I've four classes.
1. PetersonAlgorithm.java
package com.ashish.master;
public class PetersonAlgorithm {
boolean wantCS[] = {false, false};
int turn = 1;
public void requestCS(int i) {
System.out.println("Lock requested by the thread - " + i);
wantCS[i] = true;
turn = 1 - i;
while(wantCS[1-i] && turn == 1-i);
}
public void releaseCS (int i) {
wantCS[i] = false;
turn = i - 1;
System.out.println("Lock released by the thread - " + i);
}
}
If anyone feels that above algorithm is incorrect then let me know, and feel free to make suggestions.
2. Runner.java
package com.ashish.master;
public class Runner {
public static Incrementer runnableInstance = new Incrementer();
public static Thread inc1 = new Thread(runnableInstance, "0");
public static Thread inc2 = new Thread(runnableInstance, "1");
public static void main(String args[]) {
inc1.start();
inc2.start();
try{
inc1.join();
inc2.join();
} catch (InterruptedException ex) {
System.out.println("The threads have been interrupted while waiting for the join ---> " + ex.getMessage());
}
System.out.println("The total turns taken by incrementer are ----> " + runnableInstance.turns);
}
}
3. Incrementer.java - If synchronized block is used instead of the Peterson algorithm, everything works fine.
package com.ashish.master;
public class Incrementer implements Runnable {
public long turns = 0;
public PetersonAlgorithm pa = new PetersonAlgorithm();
#Override
public void run() {
System.out.println("Thread " + this.toString() + "started.....");
while(true) {
pa.requestCS(Integer.parseInt(this.toString()));
// synchronized(this) {
if(DataStore.data < 1000000) printCriticalSection();
else break;
// }
pa.releaseCS(Integer.parseInt(this.toString()));
}
}
public void printCriticalSection() {
System.out.println("The value of the number is increased by thread " +
this.toString() +" to --> " + DataStore.increase());
turns ++;
}
#Override
public String toString() {
return Thread.currentThread().getName();
}
}
4. DataStore.java A class to mock the data source -- simply increase the number
package com.ashish.master;
public class DataStore {
public static long data = 0L;
public static long increase() {
DataStore.data += 1;
return DataStore.data;
}
}

Your runnables never observe each other's monitors (wantCS and turn) as they have different instances... Each runnable needs to work with a same shared set of monitors!
Take the blue pill and make your PetersonAlgorithm variables static volatile with synchronized block access...
Or take the red pill and you create a Class for your flag monitors (wantCS) and for your indicator monitor (turn). Then just define your runnable with one "own flag", one "observed flag" and one "indicator". Both Runnables will have the same indicator instance (therefore needs to be synchronized) while the flag instances will be crossed (the own flag of R1 will be the observed flag of R2 and the own flag of R2 the observed flag of R1). You should synchronized the flag methods too as you don't want to have a flag raised or lowered while being observed.
Then few steps:
Runnables raise their Flag
Runnables turn the shared Indicator ( set to opponent runnable's id )
Wait if opponent's flag is raised and Indicator is set to opponent.
The non waiting opponent does its stuff then lowers its flag.
The waiting opponent stops waiting (opponent's flag has been lowered), does its stuff and lowers its flag.

Each of your runnable instances has its own PetersonAlgorithm instance. Thus, the two runnables don't know anything about each other and will both always get immediate access to the critical section. Try implementing your PetersonAlgorithm class as static class with static methods. Then change the lines
pa.requestCS(Integer.parseInt(this.toString()));
// ...
pa.releaseCS(Integer.parseInt(this.toString()));
into
PetersonAlgorithm.requestCS(Integer.parseInt(this.toString()));
// ...
PetersonAlgorithm.releaseCS(Integer.parseInt(this.toString()));

Related

Problem with critical section using Retrant Lock with Condition

I have a small project to synchronize multiple (two classes: ships, cars with a few instances with shared bufor class called Harbour) threads at the same time. They will be performing certain action on it. But I can't start with that until I synchronized the threads named "cars" in the Harbour. The Harbour has limited capacity and if this capacity is reached the "car" threads should be waiting until they will get signal that there's a free space to enter. I've used Retrant Lock with Condition but it doesn't work as I think.
public class Harbour {
final Lock protectNr;
final Condition protectNrCon;
int capacity;
int nrOfCars;
public Harbour(int capacity) {
this.capacity = capacity;
this.protectNr = new ReentrantLock();
this.protectNrCon = protectNr.newCondition();
}
public void carEnterHarbour(String name) {
try {
protectNr.lock();
if (this.nrOfCars == this.capacity)
protectNrCon.await();
nrOfCars++;
System.out.println(name + " enters");
System.out.println("Number of cars:" + this.nrOfCars);
protectNr.unlock();
} catch (InterruptedException e) {
System.out.println("Error");
}
}
public void carLeavingHarbour(String name) {
try {
protectNr.lock();
this.nrOfCars--;
protectNrCon.signal();
System.out.println(name + " leaving");
System.out.println("Number of cars:" + this.nrOfCars);
} finally {
protectNr.unlock();
}
}
}
public class Car extends Thread {
Harbour harbour;
public Car(Harbour harbour, String name) {
super(name);
this.harbour = harbour;
}
public void run() {
for (int i = 0; i < 10; i++) {
harbour.carEnterHarbour(getName());
harbour.carLeavingHarbour(getName());
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
int harbourCapacity = 20;
final Harbour harbour = new Harbour(harbourCapacity);
int nrOfCars = 500;
Car[] cars = new Car[nrOfCars];
for (int i = 0; i < nrOfCars; i++)
cars[i] = new Car(harbour, "Car-" + i);
for (int i = 0; i < nrOfCars; i++)
cars[i].start();
for (int i = 0; i < nrOfCars; i++)
cars[i].join();
}
}
What I was expecting after executing this code:
Car-386 leaving
Number of cars:**19**
Car-300 enters
Number of cars:**20**
Car-300 leaving
Number of cars:**19**
What I got:
Car-386 leaving
Number of cars:**20**
Car-300 enters
Number of cars:**21**
Car-295 enters
Number of cars:**22**
I also try to change int capacity to volatile int capacity and add some busy waiting but didn't work at all.
It looks like Threads are not block on Condition and I wonder why is this happening?
The documentation for Condition warns that spurious wakeups might occur (emphasis mine):
When waiting upon a Condition, a "spurious wakeup" is permitted to occur, in general, as a concession to the underlying platform semantics. This has little practical impact on most application programs as a Condition should always be waited upon in a loop, testing the state predicate that is being waited for. An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop.
Your code doesn't honor that warning.
Your carEnterHarbour() must take this possibility of spurious wakeups into account and needs
while(this.nrOfCars == this.capacity){
protectNrCon.await();
}
instead of the simple if statement.
Depending on your requirements it might be easier to use a Semaphore:
public class Harbour {
final Semaphore slots;
public Harbour(int capacity){
this.slots = new Semaphore(capacity);
}
public void carEnterHarbour(String name) {
try{
slots.acquire();
}catch (InterruptedException e){
System.out.println("Error");
}
}
public void carLeavingHarbour(String name) {
slots.release();
}
}
Note that when using a Semaphore you don't have those locks in place when entering / leaving the Harbour and therefore it is difficult to get that ordered "car entering" / "car leaving" output together with the number of currently available slots.
In the carEnterHarbour method, you are calling await() on the protectNrCon condition, which causes the current thread to wait until it is signaled. However, you are not calling signal() anywhere in the carEnterHarbour method. This means that once a thread enters the if block, it will always wait indefinitely on the condition.
You should consider calling signal() on the protectNrCon condition after you increment nrOfCars and print the message, so that other threads waiting on the condition can be unblocked.
Additionally, you should call await() in a loop to ensure that the thread waits until the condition is true, rather than waiting indefinitely. Here is an example of how you can modify the carEnterHarbour method:
public void carEnterHarbour(String name) {
try {
protectNr.lock();
while (this.nrOfCars == this.capacity) {
protectNrCon.await();
}
nrOfCars++;
System.out.println(name+" enters");
System.out.println("Number of cars:" + this.nrOfCars);
protectNrCon.signal();
} catch (InterruptedException e) {
System.out.println("Error");
} finally {
protectNr.unlock();
}
}

Java-Synchronized String result in interference

I am using a simple program where 2 threads are defined to simply count down from 10. I have a ThreadColor class simply to be able to color the 2 threads in different colors.
package com.sherif;
public class Main {
public static void main(String[] args) {
Countdown countdown = new Countdown();
CountdownThread t1 = new CountdownThread(countdown);
t1.setName("Thread 1");
t1.start();
CountdownThread t2 = new CountdownThread(countdown);
t2.setName("Thread 2");
t2.start();
}
}
class Countdown {
private int i;
String color;
public void doCountdown() {
switch (Thread.currentThread().getName()) {
case "Thread 1":
color = ThreadColor.ANSI_BLUE;
break;
case "Thread 2":
color = ThreadColor.ANSI_RED;
break;
default:
color = ThreadColor.ANSI_CYAN;
}
synchronized (color) {
for (i = 10; i > 0; i--) {
System.out.println(color + Thread.currentThread().getName() + " i= " + i);
}
}
}
}
class CountdownThread extends Thread {
private Countdown countdown;
public CountdownThread(Countdown countdown) {
this.countdown = countdown;
}
#Override
public void run() {
this.countdown.doCountdown();
}
}
I am synchronizing the for loop that counts down to avoid interference using the color object. Although I am defining the color as an instance variable that both threads share it still creates interference.
However, when I use a different string it works just fine.
I know that I can use synchronized on (this), but I would like to understand what exactly is going on.
Your color field value is not protected by simply synchronizing on the field, because the assignment statements that change the value are not synchronized.
The only thing the synchronized block does, is ensure that both threads are not running inside the block at the same time, and that's only if the value of color is referring to the same object.
Even though thread 1 is already inside the block, doesn't stop thread 2 from changing the value of the color field.
Timeline of your code could be:
Thread 1 sets color = ThreadColor.ANSI_BLUE.
Thread 1 enters block, synchronized on ANSI_BLUE object, and starts printing.
Thread 2 sets color = ThreadColor.ANSI_RED.
Thread 2 enters block, synchronized on ANSI_RED object, and starts printing.
As you can see, they are not even synchronizing on the same object, so both can be inside the synchronized block at the same time.
Both treads continue printing in parallel.

Java: Fail in synchronizing threads

I have the following code:
for (int iThreadCounter = 1; iThreadCounter <= CONNECTIONS_NUM; iThreadCounter++){
WorkThread wt = new WorkThread(iThreadCounter);
new Thread(wt).start();
m_arrWorkThreadsToCreate.add(wt);
}
Those threads calls the following code:
int res = m_spLegJoin.call(m_workTread, m_workTread.getConfId());
And this is the call method inside LegJoinSp class:
public class LegJoinSp extends ConnEventSp {
private static final int _LEG_JOIN_ACTION_CODE = 22;
private static int m_nLegId = Integer.valueOf(IniUtils.getIniValue("General", "LEG_ID_START"));
private final Lock m_lock = new ReentrantLock();
public int call(WorkThread a_workThread, String a_sConfId) {
synchronized (this) {
//m_lock.lock();
m_nLegId++;
boolean bPass = false;
Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId);
if (super.call(a_workThread, a_sConfId, _LEG_JOIN_ACTION_CODE, "" + m_nLegId) == 0) {
bPass = true;
} else {
bPass = false;
}
//m_lock.unlock();
if (bPass) {
Log4jWrapper.writeLog(LogLevelEnum.DEBUG, "LegJoinSp - call", "a_workThread = " + a_workThread.getThreadId() + " a_sConfId = " + a_sConfId + " returned leg id " + m_nLegId);
return m_nLegId;
} else {
return -1;
}
}
}
public Lock getLock() {
return m_lock;
}
}
I've got 2 threads calling this call() method.
m_nLegId is initiated with 100.
As you can see I have tried to lock the method with both
synchronized(this)
and
m_lock.lock() and m_lock.unlock()
The problem is that when I first get to if (bPass) inner code, it write 102 to my log as the m_nLegId value. However I expect it to be 101 because of the m_nLegId++; statement.
It seems that the second thread manage to get inside the code before the synchronize block ends for the first thread execution.
How can I fix that?
Thank you
For me your bug is related to the fact that m_nLegId is a static field and you try to synchronize access on the current instance instead of the class such that you don't properly prevent concurrent modifications of your field.
I mean
synchronized (this) {
Should rather be
synchronized (LegJoinSp.class) {
NB: In case you only need a counter, consider using an AtomicInteger for your field instead of an int.
The thing is you are creating a new object with every thread, but the way you applied the lock is applicable only to same object (as you applied the lock on the this).
So if you want to apply the lock on the class level, then you can create a static object and apply the lock on that object which can serve the purpose you wanted to achieve (if I understood your problem correctly based on the comments)

Calling a synchronized from inside a non-synchronized method

I'm experimenting with Threads and it's not working as expected, despite the fact I've applied Synchronization.
I have a method
private synchronized void printStatus(){
System.out.println("\t\t\t" + Thread.currentThread().getName());
System.out.println("\t\t\tCookies: " + contents);
}
and so I'm expecting, that when ever called, in the output I will get one line after another. But that is not what happens. My output looks like this:
homerThread
Cookies: 0
margeThread
0 cookies were Removed
Cookies: 0
homerThread
3 cookies were Put
Cookies: 3
0 cookies were Removed
margeThread
Cookies: 3
3 cookies were Put
homerThread
Cookies: 6
4 cookies were Removed
margeThread
Cookies: 2
1 cookies were Put
homerThread
Cookies: 3
3 cookies were Removed
margeThread
Cookies: 0
....
As you can see, there are a lot of lines that are not synchronized properly
Why is this happening?
I've included my entire code below for completeness;
Main.java class
public class Main {
public static void main(String[] args) {
CookieJar jar = new CookieJar();
Homer homer = new Homer(jar);
Marge marge = new Marge(jar);
Thread homerThread = new Thread(homer);
homerThread.setName("homerThread");
Thread margeThread = new Thread(marge);
margeThread.setName("margeThread");
homerThread.start();
margeThread.start();
}
}
Homer.java
import java.util.Random;
public class Homer implements Runnable {
CookieJar jar;
public Homer(CookieJar jar) {
this.jar = jar;
}
public void eat(int amnt) {
jar.getCookie(amnt);
}
public void run() {
Random random = new Random();
for(int i = 0; i < 10; i++){
eat(random.nextInt(5));
}
}
}
Marge
import java.util.Random;
public class Marge implements Runnable {
CookieJar jar;
public Marge(CookieJar jar) {
this.jar = jar;
}
public void bake(int cookie) {
jar.putCookie(cookie);
}
public void run() {
Random random = new Random();
for(int i = 0; i < 10; i++){
bake(random.nextInt(5));
}
}
}
CookieJar.java
public class CookieJar {
int contents = 0;
boolean hasCookie = false;
public void putCookie(int amount) {
printStatus();
contents += amount;
System.out.println(amount + " cookies were Put");
}
public void getCookie(int amount) {
printStatus();
contents -= amount;
System.out.println(amount + " cookies were Removed");
}
private synchronized void printStatus(){
System.out.println("\t\t\t" + Thread.currentThread().getName());
System.out.println("\t\t\tCookies: " + contents);
}
}
*Note: Yes I realize that Homer might end up eating negative amount of cookies, which may or may not be possible.
OK, here's what synchronized does: It prevents two or more threads from synchronizing on the same object at the same time. It does not do anything else. It does not prevent two threads from entering the same synchronized method at the same time (the threads could be calling the same method on different instances). Synchronizing on an object does not prevent other threads from modifying that object. (The other threads might be in un-synchronized methods).
If you want to prevent other threads from printing messages between the two lines that printStatus() prints, then it is not enough to only synchronize printStatus(). You must synchronize every thread that can use System.out. Here's how I would do it:
private void printStatus() {
synchronized (System.out) {
System.out.println("\t\t\t" + Thread.currentThread().getName());
System.out.println("\t\t\tCookies: " + contents);
}
}
public void putCookie(int amount) {
printStatus();
contents += amount;
synchronized (System.out) {
System.out.println(amount + " cookies were Put");
}
}
...
I am synchronizing on System.out here to illustrate a point. System.out is the thing that I want to protect It does not matter what other threads and what other synchronization objects I have in my program, if every method that tries to write to System.out does so from inside synchronized (System.out), then the outputs will all be correctly interleaved.
Extra Credit:
In production code, I would have done this instead:
private static Object consoleLock = new Object();
...
synchronized (consoleLock) {
System.out.println(...);
...
}
...
It will have the same effect as synchronizing on System.out as long as I consistently use consoleLock everywhere, but it has the advantage that the lock variable is private. That way, I know that no other programmer is going to be synchronizing on my lock for some other reason. (They'd have to be pretty crazy to synchronize on System.out for any other reason, but then there are some crazy developers out there.)
Also note: I made consoleLock static because System.out is static. There is only one System.out, so it's important that I have only one lock object.
The problem is that these lines:
System.out.println(amount + " cookies were Put");
System.out.println(amount + " cookies were Removed");
Are not synchronized on jar. If you look at only the xThread and Cookies: N output, which are synchronized, those are always properly ordered.
You should also synchronize your getCookie and putCookie methods, otherwise they will interleave with the printStatus method.

Synchronizing threads

So I have a code:
public void runThreads(int number)
{
List<Thread> threadList = new ArrayList<Thread>();
for (int i = 0; i < number; i++)
{
Thread t = new MyThread(getRandomPerson(),i);
threadList.add(t);
}
for (Thread x : threadList)
{
x.start();
}
}
So I am adding threads to my list of threads and then starting this threads.
This is MyThread class:
public class MyThread extends Thread
{
Person person;
int number;
public MyThread(Person person, int number)
{
this.person = person;
this.number = number;
}
#Override
public void run()
{
try
{
synchronized (this)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
I wanted to make a program which creates the threads, adds them to the list, invokes them but each thread should wait until the previous ended its task.
So output should be like :
1 Surname
/** Waitning second */
1 person.toString()
/** Waiting second*/
And then the second thread start invoking:
2 Surname
....
How to achieve this using synchronized? I tried different ways to use synchronized but it failed.
public class MyThread extends Thread
{
private static Object lock = new Object();
...
synchronized (lock)
{
Thread.sleep(1000);
System.out.println(number + "\t" + person.getSurname());
Thread.sleep(1000);
System.out.println(number + "\t" + person.toString());
}
...
That way you will get the same person's surname and toString() in order. You won't enforce strict ordering on the people, person 7 may still go before person 1.
You need a common lock - at the moment you are synchronizing on this, which is different for each thread. Try something like:
private static final Object lock = new Object();
and synchronize on that static (therefore shared) variable instead.
If you must use threads and if you must have order of execution, then you can do a t.join() immediately after t.start() - this will ensure the following flow:
- Main Thread
- loop
- start child thread
- wait for child thread to finish
- continue loop
- Exit Main thread
But, as pointed before, you don't need threads to do this since you can see that there is absolutely no gain from this approach (apart from academical) and it's detrimental in fact.
And special thanks to #assylias.

Categories