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());
}
}
}
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 learned that threads can lock onto "the resources", let's say an object, they're using so that only one at a time is allowed to use and modify it which is the problem of synchronization. I created two different instances of one class and fed it to my threads, trying to make sure they're locking on different "resources". How ever they still behave as though they've locked on same resources? I'm confused as I haven't had any experience and knowledge regarding threads.
So this is a code I modified from an online tutorial to try what I was thinking about:
public class TestThread {
public static void main(String args[]) {
PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
PrintDemo PD2 = new PrintDemo("No.2");
ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );
T1.start();
T2.start();
// wait for threads to end
try {
T1.join();
T2.join();
} catch ( Exception e) {
System.out.println("Interrupted");
}
}
}
class ThreadDemo extends Thread {
private Thread t;
private String threadName;
PrintDemo PD;
ThreadDemo( String name, PrintDemo pd) {
threadName = name;
PD = pd;
}
public void run() {
synchronized(PD) {
PD.printCount();
}
System.out.println("Thread " + threadName + " exiting.");
}
public void start () {
System.out.println("Starting " + threadName );
if (t == null) {
t = new Thread (this, threadName);
t.start ();
}
}
}
class PrintDemo {
private String name;
PrintDemo(String name) {
this.name = name;
}
public void printCount() {
try {
for(int i = 5; i > 0; i--) {
System.out.println(name + " Counter --- " + i );
}
} catch (Exception e) {
System.out.println("Thread interrupted.");
}
}
}
It should be different each time I run, but it always the same:
output:
Starting Thread - 1
Starting Thread - 2
No.1 Counter --- 5
No.1 Counter --- 4
No.1 Counter --- 3
No.1 Counter --- 2
No.1 Counter --- 1
Thread Thread - 1 exiting.
No.2 Counter --- 5
No.2 Counter --- 4
No.2 Counter --- 3
No.2 Counter --- 2
No.2 Counter --- 1
Thread Thread - 2 exiting.
edit #1: I put the entire code as you asked. i also tested the code without overriding start. it had the same result.
If you add a
Thread.sleep(1000)
between each tick of your PrintDemo, you will likely see that both threads do 5, then 4, then 3, etc. Right now the first thread is being too fast, it completes faster than the 2nd thread can be started by the main thread.
Synchronization has no effect here, both threads synchronize on different resources, which has no effect. After proving (with the Thread.sleep) that both threads execute at the same time, then add synchronization on a shared object, and both threads will fully execute one after the other, even with the waiting.
The problem is in your ThreadDemo.start() method.
Your ThreadDemo class is declared with extends Thread, but you never actually use it as a thread. Instead, the real thread objects are created inside ThreadDemo.start().
t = new Thread (this, threadName);
t.start ();
Here's what probably is happening:
Main thread calls T1.start(). It creates a new thread, which takes some time, and then it starts the thread.
The new thread starts printing its five lines, while the main thread simultaneously calls T2.start().
The T2.start() call creates another new thread, which takes some time. Meanwhile, the other thread still is printing. It doesn't print very many lines, and system.out is buffered, so chances are, it is able to print all of them before any actual I/O happens. Meanwhile...
...The main thread still is creating that T2 thread. It takes some time.
Finally, the main thread is able to start the T2 thread, which prints its five lines, and...
...end of story. That's how it probably goes down.
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
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?
This question already has answers here:
Synchronized block not working
(8 answers)
Closed 7 years ago.
I have difficulty understanding synchronized and reentrant lock. Here is small program I was experimenting with:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Reentr {
public static void main(String[] args) {
ExecutorService eService = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 2; i++) {
eService.execute(new process());
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
eService.shutdown();
}
}
class process implements Runnable {
int count = 0;
#Override
public void run() {
processTest();
}
public synchronized void processTest() {
try {
for (int i = 1; i <= 2; i++) {
count += i;
System.out.println("count value for " + Thread.currentThread().getName() + " is " + count);
}
} finally {
System.out.println("count for " + Thread.currentThread().getName() + " is " + count);
}
}
}
The output was:
count value for pool-1-thread-2 is 1
count value for pool-1-thread-1 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
If we see in the output two thread are in the synchronized block. I was under the impression that one thread has to complete the execution of synchronized method, after that other thread will enter the method.
Ideally, I was expecting result something like this
count value for pool-1-thread-1 is 1
count value for pool-1-thread-1 is 3
count for pool-1-thread-1 is 3
count value for pool-1-thread-2 is 1
count value for pool-1-thread-2 is 3
count for pool-1-thread-2 is 3
I have replaced synchronized method with synchronized block and re-entrant locks. However, I still have the same output. What am I missing?
The two threads are not synchonizing on the same object.
You have two different instances of process (as an aside; you should always name classes with a Capital letter). The synchronized keyword is equivalent to:
public void processTest() {
synchronized(this) {
// etc..
}
}
If you want one thread to run after the other, they must synchronize on the same object. If you did this, for example:
class process implements Runnable {
// note that this is static
private static final Object lock = new Object();
public void processTest() {
synchronized(lock) {
// your code
}
}
}
Then your code would have one thread run after the other. Another way to do it would be to pass the lock into the Objects constructor, or the same instance of a Semaphore, etc.
When an instance method is declared synchronized, it synchronizes on the object instance. Since you are running with a new process() in each loop iteration, the object instances are different, so the synchronization is meaningless. Try creating a single process object and passing that to both of the threads you start.
When you do, also move the count instance variable into the processTest method. That way it will be thread safe.