Alternate between two threads (producer-consumer) - java

I'm attempting to edit my program so that the incrementer and decrementer classes are called alternatively, which incrementer being performed first. My aim is to be able to print the value of a shared variable (sharedValue) after each increment/decrement and hopefully see it toggle between 1 and 0. Below is the code for my main class, a semaphore class and incrementer class (there is a class decrementer which is styled the same way as icrementer so i didn't include it).
main class
public class Main extends Thread {
private static int sharedValue = 0;
private static Semaphore semaphore = new Semaphore(1);
static int numberOfCycles = 20000;
public static void increment() {
semaphore.down();
sharedValue++;
semaphore.up();
}
public static void decrement() {
semaphore.down();
sharedValue--;
semaphore.up();
}
public static void main(String[] args) throws InterruptedException {
incrementer inc = new incrementer(numberOfCycles);
inc.start();
inc.join();
decrementer dec = new decrementer(numberOfCycles);
dec.start();
dec.join();
System.out.println(sharedValue);
}
}
Semaphore class
private int count;
// Constructor
public Semaphore(int n) {
count = n;
}
// Only the standard up and down operators are allowed.
public synchronized void down() {
while (count == 0) {
try {
wait(); // Blocking call.
} catch (InterruptedException exception) {
}
}
count--;
}
public synchronized void up() {
count++;
notify();
}
incrementer Class
public class incrementer extends Thread{
private int numberOfIncrements;
public incrementer(int numOfIncrements){
numberOfIncrements = numOfIncrements;
}
public void run(){
for(int i = 0; i <= numberOfIncrements; i++){
Main.increment();
}
}
}
Thanks in advance!
So I have been reading through my notes and it occurred to me that I could use another mutex semaphore which can determine if the buffer is full or empty. Am I right with this approach?

Thread.Join causes your main thread to wait for the completion of the incrementer, then starts the decrementer and then waits for decrementer to complete. If you want them to run concurrently, remove the two Thread.Join calls:
public static void main(String[] args) throws InterruptedException {
incrementer inc = new incrementer(numberOfCycles);
decrementer dec = new decrementer(numberOfCycles);
inc.start();
dec.start();
}
To print the shared value after each increment or decrement, move the println call to the increment and decrement functions of your main class:
public static void increment() {
semaphore.down();
sharedValue++;
System.out.println(sharedValue);
semaphore.up();
}
public static void decrement() {
semaphore.down();
sharedValue--;
System.out.println(sharedValue);
semaphore.up();
}
Also note that even with these changes you won't be observing the toggling between 1 and 0. This is because the two threads don't start at the same time, and even if they did (e.g. using CyclicBarrier) you can't control the scheduling so they would progress differently. If you really want to observe this output, you should make each thread wait for 1ms before and after calling semaphore.up() in order to give the other thread a chance to wait and acquire a permit from the semaphore.
public static void increment() {
semaphore.down();
sharedValue++;
System.out.println(sharedValue);
try {
Thread.sleep(1); //give time to other threads to wait for permit
semaphore.up();
Thread.sleep(1); //give time to other threads to acquire permit
} catch (InterruptedException ex) {
}
}
There are more robust ways to get this kind of output from two threads, but I didn't want to make major modifications to your code.

Related

Print 1-1000 with two threads (even and odd) from the same class

So my task is this:
Instantiate two object of the same class
Provide a constructor argument, to designate a thread as even and another as odd .
Start both threads right one after other
Odd thread prints odd numbers from 0 to 1000
Even thread prints even numbers from 0 to 1000
However they should be in sync the prints should be 1 , 2 , 3 , 4 .....
One number on each line
However I can't seem to get the locks to release correctly. I've tried reading some of the similar problems on here but they all use multiple classes. What am I doing wrong?
Edit: My main class is doing this -
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
and my output is -
odd: 1
even: 2
...
public class NumberPrinter extends Thread {
private String name;
private int starterInt;
private boolean toggle;
public NumberPrinter(String name) {
super.setName(name);
this.name=name;
if(name.equals("odd")) {
starterInt=1;
toggle = true;
}
else if(name.equals("even")) {
starterInt=2;
toggle = false;
}
}
#Override
public synchronized void run() {
int localInt = starterInt;
boolean localToggle = toggle;
if(name.equals("odd")) {
while(localInt<1000) {
while(localToggle == false)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = false;
notify();
}
}
else {
while(localInt<1000) {
while(localToggle == true)
try {
wait();
}catch(InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println(name+": "+localInt);
localInt +=2;
localToggle = true;
notify();
}
}
}
}
The key problem here is that the two threads have no way to coordinate with each other. When you have a local variable (localToggle in this case) nothing outside the method can observe or alter its value.
If you share one object with both threads, however, its state can change, and if used correctly, those state changes will be visible to both threads.
You will see examples where the shared object is an AtomicInteger, but when you use synchronized, wait() and notify(), you don't need the extra concurrency overhead built into the atomic wrappers.
Here's a simple outline:
class Main {
public static main(String... args) {
Main state = new Main();
new Thread(new Counter(state, false)).start();
new Thread(new Counter(state, true)).start();
}
int counter;
private static class Counter implements Runnable {
private final Main state;
private final boolean even;
Counter(Main state, boolean even) {
this.state = state;
this.even = even;
}
#Override
public void run() {
synchronized(state) {
/* Here, use wait and notify to read and update state.counter
* appropriately according to the "even" flag.
*/
}
}
}
}
I'm not clear whether using wait() and notify() yourself is part of the assignment, but an alternative to this outline would be to use something like a BlockingQueue to pass a token back and forth between the two threads. The (error-prone) condition monitoring would be built into the queue, cleaning up your code and making mistakes less likely.
I finally got it working in a way that meets the standards required by my assignment.
Thank you all for your input. I'll leave the answer here for anyone who might need it.
public class Demo {
public static void main(String[] args) {
NumberPrinter oddPrinter = new NumberPrinter("odd");
NumberPrinter evenPrinter = new NumberPrinter("even");
oddPrinter.start();
evenPrinter.start();
System.out.println("Calling thread Done");
}
public class NumberPrinter extends Thread {
private int max = 1000;
static Object lock = new Object();
String name;
int remainder;
static int startNumber=1;
public NumberPrinter(String name) {
this.name = name;
if(name.equals("even")) {
remainder=0;
}else {
remainder=1;
}
}
#Override
public void run() {
while(startNumber<max) {
synchronized(lock) {
while(startNumber%2 !=remainder) {
try {
lock.wait();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name+": "+startNumber);
startNumber++;
lock.notifyAll();
}
}
}
}

What's the difference between acquire(number) and acquire() in a loop

I had to make 2 threads that execute alternately and also one of them has to execute N times more than the other.
public void init(int count) {
semaphore1 = new Semaphore(1);
semaphore2 = new Semaphore(0);
num=count;
}
class F1Thread extends Thread {
public void run() {
semaphore1.acquire();
for(int i=0;i<num;i++)
f1();
semaphore2.release();
}
class F2Thread extends Thread {
public void run() {
semaphore2.acquire();
f2();
semaphore1.release();
}
This is my solution but before that i tried acquiring all the permits instead of 1 and doing a loop
public void init(int count) {
semaphore1 = new Semaphore(count);
semaphore2 = new Semaphore(0);
num=count;
}
class F1Thread extends Thread {
public void run() {
semaphore1.acquire(count);
f1();
semaphore2.release();
}
class F2Thread extends Thread {
public void run() {
semaphore2.acquire();
f2();
semaphore1.release(count);
}
My point is
for(int i=0;i<number;i++)
semaphore.acquire();
and
semaphore.acquire(number);
shouldn't perform the same ?
If the semaphore has 5 permits,
10 times acquire() would acquire 5 and block.
acquire(10) would immediately block, till 10 permits are released.
However I did not find this behaviour in the javadocs, nor after eyeing the sources.
It seems that a greedy acquire(number) could mean other threads with a lesser number always pass first.
Unfortunately I did not find a specification.

Java Multithreading - Threadsafe Counter

I'm starting off with a very simple example in multithreading. I'm trying to make a threadsafe counter. I want to create two threads that increment the counter intermittently to reach 1000. Code below:
public class ThreadsExample implements Runnable {
static int counter = 1; // a global counter
public ThreadsExample() {
}
static synchronized void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter++;
}
#Override
public void run() {
while(counter<1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
From what I can tell, the while loop right now means that only the first thread has access to the counter until it reaches 1000. Output:
Thread-0: 1
.
.
.
Thread-0: 999
Thread-1: 1000
How do I fix that? How can I get the threads to share the counter?
You could use the AtomicInteger. It is a class that can be incremented atomically, so two seperate threads calling its increment method do not interleave.
public class ThreadsExample implements Runnable {
static AtomicInteger counter = new AtomicInteger(1); // a global counter
public ThreadsExample() {
}
static void incrementCounter() {
System.out.println(Thread.currentThread().getName() + ": " + counter.getAndIncrement());
}
#Override
public void run() {
while(counter.get() < 1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
Both threads have access to your variable.
The phenomenon you are seeing is called thread starvation. Upon entering the guarded portion of your code (sorry I missed this earlier), other threads will need to block until the thread holding the monitor is done (i.e. when the monitor is released). Whilst one may expect the current thread pass the monitor to the next thread waiting in line, for synchronized blocks, java does not guarantee any fairness or ordering policy to which thread next recieves the monitor. It is entirely possible (and even likely) for a thread that releases and attempts to reacquire the monitor to get hold of it over another thread that has been waiting for a while.
From Oracle:
Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.
Whilst both of your threads are examples of "greedy" threads (since they repeatedly release and reacquire the monitor), thread-0 is technically started first, thus starving thread-1.
The solution is to use a concurrent synchronization method that supports fairness (e.g. ReentrantLock) as shown below:
public class ThreadsExample implements Runnable {
static int counter = 1; // a global counter
static ReentrantLock counterLock = new ReentrantLock(true); // enable fairness policy
static void incrementCounter(){
counterLock.lock();
// Always good practice to enclose locks in a try-finally block
try{
System.out.println(Thread.currentThread().getName() + ": " + counter);
counter++;
}finally{
counterLock.unlock();
}
}
#Override
public void run() {
while(counter<1000){
incrementCounter();
}
}
public static void main(String[] args) {
ThreadsExample te = new ThreadsExample();
Thread thread1 = new Thread(te);
Thread thread2 = new Thread(te);
thread1.start();
thread2.start();
}
}
note the removal of the synchronized keyword in favor of the ReentrantLock within the method. Such a system, with a fairness policy, allows long waiting threads a chance to execute, removing the starvation.
Well, with your code I don't know how to get "exactly" intermittently, but if you use Thread.yield() after call incrementCounter() you will have a better distribution.
public void run() {
while(counter<1000){
incrementCounter();
Thread.yield();
}
}
Otherwise, to get what you propose, you can create two different thread class (ThreadsExample1 and ThreadsExample2 if you want), and another class to be a shared variable.
public class SharedVariable {
private int value;
private boolean turn; //false = ThreadsExample1 --> true = ThreadsExample2
public SharedVariable (){
this.value = 0;
this.turn = false;
}
public void set (int v){
this.value = v;
}
public int get (){
return this.value;
}
public void inc (){
this.value++;
}
public void shiftTurn(){
if (this.turn){
this.turn=false;
}else{
this.turn=true;
}
}
public boolean getTurn(){
return this.turn;
}
}
Now, the main can be:
public static void main(String[] args) {
SharedVariable vCom = new SharedVariable();
ThreadsExample1 hThread1 = new ThreadsExample1 (vCom);
ThreadsExample2 hThread2 = new ThreadsExample2 (vCom);
hThread1.start();
hThread2.start();
try {
hThread1.join();
hThread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
And you have to change your line static int counter = 1; // a global counter
for private SharedVariable counter;
And the new run is:
public void run() {
for (int i = 0; i < 20; i++) {
while (!counter.getTurno()){
Thread.yield();
}
System.out.println(this.counter.get());
this.counter.cambioTurno();
}
}
}
Yes, it is another code, but I think it can help you a little bit.

Basic multi-threading issue

package demo5;
class Process extends Thread {
static int counter = 0;
public static synchronized void increment() { counter++; }
public void run() {
for (int i = 0; i < 1000000; i++)
{
increment();
}
System.out.println("Done.");
}
}
public class App {
public static void main(String[] args) throws InterruptedException {
Process p1 = new Process();
Process p2 = new Process();
p1.start();
p2.start();
p1.join();
p2.join();
System.out.println("Value of count is :" + p1.counter);
}
}
if I declare the increment function as NON-STATIC function the value of the counter at the end will NOT be 2 million.
on the other hand, it works properly when the increment method is defined as static.
As far as I know there will be only ONE increment function for all the Process objects.. so why do I have to declare it as a static method..?
thanks
Declaring it static will cause the synchronized to lock on the Process.class instance. So all threads running will block on the Object within the increment method. Removing the static will cause each thread to only block on the Thread instance (which in your case there are two).
As a result your counter variable is being incremented in parallel and as noted many times, int incrementing is not thread-safe.
As far as I know there will be only ONE increment function for all the Process objects
There is one increment function for the Process class, but the synchronization is done on the Object and not the method for instance:
class Process{
public synchronized void increment() { counter++; }
}
Is equivallent to:
class Process{
public void increment() {
synchronized(this){
counter++;
}
}
Edit: To answer Rouki's question.
class Process{
public static synchronized void increment() { counter++; }
}
Is equivallent to
class Process{
public void increment() {
synchronized(Process.class){
counter++;
}
}
You may want to replace your int counter with an AtomicInteger counter - this way you can remove the synchronized keyword from the method, and it shouldn't matter if the method is a static or instance method.

Thread output inconsistent even when using synchronized keyword

I am very new to threads. I wrote a code and expected my output as 20000 consistently. But that's not the case. Please find the code below:
class Runner4 implements Runnable {
static int count = 0;
public synchronized void increase() {
count++;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
}
public class threading4 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runner4());
t1.start();
Thread t2 = new Thread(new Runner4());
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Runner4.count);
}
}
Any explanation?
Thanks!!
You are synchronizing on two different objects in your code (corresponding to the two objects you created). As such, there is no protection of the shared static variable, and you get unpredictable results. Basically, there is no effective synchronization going on in your program. You can fix this with a simple modification.
Change:
public synchronized void increase(){
count++;
}
To:
public void increase(){
synchronized(Runner4.class) {
count++;
}
}
Note that I am not saying this is the best way to accomplish this kind of synchronization - but the important take-away is that, if you are modifying a class level variable, you need class level synchronization as well.
Your code would work if count was not static.
public synchronized void increase() {
// method body
}
is equivalent to
public void increase() {
synchronized(this) {
// method body
}
}
Since count is static, both t1 and t2 are accessing it with different locks, resulting in non-deterministic behavior. Either make Runner4.increase synchronize on a common lock (Runner4.class or a private static lock object would work just fine), or make count non-static.
The way you're trying to achieve what you want is is not really the best way.
A better way to do it is define a class called Counter, as the following:
public class Counter
{
int count;
public Counter()
{
count = 0;
}
public synchronized void increase() {
count++;
}
public int getCount()
{
return count;
}
}
The class has the methods of increasing the counter and getting it.
What you need to do now is have a Counter object to be shared by two threads that call the increase() method. So your thread class would look like this:
class Runner4 extends Thread {
Counter count;
public Runner4(Counter c)
{
count = c;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count.increase();
}
}
}
Notice that the class takes a Counter object and calls the increase method. Also the class extends Thread instead of implementing Runnable. There is really no much difference, it's just now your Runner4 can use Thread class methods.
From your main defines a Counter object and two Runner4 threads, and then pass the Counter object to each one of them:
public static void main(String[] args) {
Counter count = new Counter();
Thread t1 = new Runner4(count);
t1.start();
Thread t2 = new Runner4(count);
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(count.getCount());
}

Categories

Resources