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?
Related
output :
Thread1 Start !!
Thread2 Start !!
Thread2 End !! 100001
Thread1 End !! 100001
i think output is
{1,10001} or {10000,10001}
because of sync...
import java.util.*;
public class Main2 {
public static int shared = 0;
public synchronized static void sharedIncrease(long amount) {
while(amount-->0) shared++;
}
public static void main(String args[]) throws Exception {
StrangeThread t1 = new StrangeThread(100000);
StrangeThread t2 = new StrangeThread(1);
t1.start();
t2.start();
}
}
class StrangeThread extends Thread {
long amount;
int thrdNum;
static int cnt = 1;
StrangeThread(long value) {
amount = value;
thrdNum = cnt++;
}
public void run() {
System.out.println("Thread"+thrdNum+" Start !! ");
Main2.sharedIncrease(this.amount);
System.out.println("Thread"+thrdNum+" End !! "+Main2.shared);
}
}
Consider the following sequence of operations
Thread 1 starts. Prints Thread1 Start !!
Thread 2 starts. Prints Thread2 Start !!
Thread 1 acquires the lock and executes the logic in sharedIncrease (Thread 2 is blocked). When the method returns, shared will be 100000.
Now, thread 2 acquires the lock and executes. At the end shared will be 100001.
Thread 2 prints Thread2 End !!
Thread 1 prints Thread1 End !!
At points 5 and 6, value of shared is 100001. (You can reverse 5 and 6 too; the result would be the same).
The key is that thread 1 wasn't able to print before thread 2 increments as part of its execution. Thus, you see the same result for both.
I'm just starting the basics of threading in java.The synchronized keyword tells the scheduler not to context switch while in the middle of a thread execution. Also, race condition happens when more a thread tries to access the same resource. With that in mind, I created a simple class to demonstrate the concept to myself.
public class DemoThread{
int i = 1;
public void runThreads() {
Thread t1 = new Thread(new Runnable () {
#Override
public void run() {
synchronized(this) {
i++;
System.out.println("Thread 1: " + i);
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized(this) {
i--;
System.out.println("Thread 2: " + i);
}
}
});
for (int k = 0; k <=100; k++) {
t1.start();
t2.start();
}
}
}
I simply have a forloop at the bottom to execute these threads 100 times. However, I get this error in the console:
Thread 2: 1Exception in thread "main"
Thread 1: 1
java.lang.IllegalThreadStateException
at java.base/java.lang.Thread.start(Thread.java:795)
at thread_demo.DemoThread.runThreads(DemoThread.java:31)
at thread_demo.main.main(main.java:9)
Why is that?
The start() method in the Thread class has the following lines:
if (threadStatus != 0)
throw new IllegalThreadStateException();
The threadStatus is used to signalize the status of the given Thread. If it's 0 it means that the Thread has not yet been started. The code above means that, if You will try to invoke start() on the Thread that is already running - the IllegalThreadStateException will be thrown.
The specific error occurs because You are calling start() method more than once for the given threads both t1 and t2
This code:
for (int k = 0; k <=100; k++) {
t1.start();
t2.start();
}
starts t1 and t2 more than once. It is prohibited.
You can't start the same thread multiple times.
Example
The following code is shows how no race condition in thread works, but I don't get the difference between with the synchronized and without it. I thought the static variable counter will be added to 20000 anyway but it turned out that without synchronized counter would be less than 20000. Can you please explain how threads work in this case? Also, in Java, are threads are actually not running "concurrently", instead are they taking turns to run for a while?
public class NoRaceCondition implements Runnable {
private static int counter = 0;
private static Object gateKeeper = new Object();
public static void main(String[] args) {
Thread t1 = new Thread(new NoRaceCondition());
Thread t2 = new Thread(new NoRaceCondition());
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) { e.printStackTrace(); }
System.out.printf("counter = %d\n", counter);
}
public void run() {
synchronized (gateKeeper) {
for (int i = 0; i < 10000; i++) {
{
counter++;
}
}
}
}
}
You can think of count++ as 3 separate steps.
read the value of count
increment the value
override count with the new incremented value
When multiple thread execute the above steps concurrently, race conditions may occur. 1 example of race condition is
Let count = 1
Let there be 2 threads named A and B
Thread A reads the value of count and get 1
Thread B reads the value of count and get 1
Thread A increments its value and get 2
Thread B increments its value and get 2
Thread A writes the value to count
count is now 2
Thread B writes the value to count
count is now 2 again when it's expected to be 3 after 2 increments
I am trying out codes with multiple threads.
Below is my code:
package com.thread.practice;
public class ThreadPratice1 {
public static void main(String[] args) {
MyRunnable r = new MyRunnable();
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
package com.thread.practice;
public class MyRunnable implements Runnable {
private static int i = 0;
#Override
public void run() {
for(i = 0; i <10;i++){
System.out.println("Thread: "+ Thread.currentThread().getName()
+" value of i: "+i);
try {
//System.out.println("Thread: "+ i);
Thread.sleep(1000);
//System.out.println("inside runnable: "+Thread.currentThread().getState());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
But in the output it is always printing the value of i as 0 twice in the beginning.
Output is coming kind of like this:
Thread: Thread 1 value of i: 0
Thread: Thread 2 value of i: 0
Thread: Thread 1 value of i: 2
Thread: Thread 2 value of i: 2
Thread: Thread 1 value of i: 3
Thread: Thread 2 value of i: 4
Thread: Thread 1 value of i: 5
Thread: Thread 2 value of i: 6
Thread: Thread 1 value of i: 7
Thread: Thread 2 value of i: 8
Thread: Thread 1 value of i: 9
May someone please help me in understanding this issue?
Because the value of i at the begging of the execution of the two threads is 0.
In other words, thread one and thread two stared almost at the same time, so the two of them set the i to 0 for the first loop.
for(i = 0; i <10;i++) {
Then the value changes between thread because you made i static. so it will be shared between your two threads.
You made "i" static, which means it will be the same over all threads and objects. Take away the static modifier and your code will work properly.
edit: I misinterpreted what you asked- don't set i to 0 in the for loop, it will look something like this:
for(;i<10;i++) { /*mycode*/}
One of these two is probably what you want anyway, your question was a little bit vague
value of i is incremented by the for loop only after the loop is executed. Execution of for loop takes a finite amount of time. Since you are starting the threads together (almost), both the threads may or may not print i after the other thread has finished one loop. Since you are not doing to ensure thread safety, the result will be unpredictable like the one you got.
First, You shouldn't use the primitive int type for concurrency, it's not thread safe and it maybe will cause Race Condition,
and try to use AtomicInteger to replace int, it's thread safe. the example maybe:
public class ThreadPratice1 {
public static void main(String[] args) {
AtomicInteger number = new AtomicInteger(0);
MyRunnable r = new MyRunnable(number);
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
t1.start();
t2.start();
}
}
class MyRunnable implements Runnable {
private AtomicInteger number;
public MyRunnable(AtomicInteger number) {
this.number = number;
}
#Override
public void run() {
while (number.get() < 10) {
System.out.println("Thread: " + Thread.currentThread().getName()
+ " value of i: " + number.getAndIncrement());
}
}
}
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().