can multiple threads with different objects of same runnable class overlap - java

Does creating a new object everytime of runnable class and passing it to Thread create multithreading problems.
For example:
class exmpl implements Runnable {
int a = 0;
exmpl(int x) {
a = x;
}
}
public class toRun {
public static void main(String[] args) {
Thread t = new Thread(new exmpl(5));
Thread t1 = new Thread(new exmpl(6));
t.start();
t1.start();
}
}
Will the two thread overlap ? ie. will the value of a for t be 5 and for t1 be 6 always?

The value of a in the exmpl instance that you construct for the t thread is initially set to 5, and the value of a in the other exmpl instance is initially set to 6, but a is not a final variable, and you have not shown us the run() method. Whether or not the two a fields will ever change depends on what the run() method does with them.

Both t and t1 are totally different objects, the value of a in each instance will be kept unless you modified it.

Yes, of course! The whole point of threads is that is so that multiple threads (even if they're different objects of class thread will run at once.
Think about it:
If it were impossible to run multiple threads at once, then wouldn't you just use individual methods? That way, the code would run in a single order, going from 1 to 2 to 3.
The thing is, java has something called a thread. The whole point of this thread is so that instead of going from 1 to 2 to 3, the compiler can execute 1 2 and 3 all at the same time.

Related

In which cases we need to synchronize a method?

Let's say I have the following code in Java
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
}
And I create two threads T1 and T2
Thread T1 = new Thread(c1);
Thread T2 = new Thread(c2);
Where c1 and c2 are two different instances of the class SynchronizedCounter.
It is really needed to synchronize the method increment? Because I know that when we use a synchronized method, the thread hold a lock on the object, in this way other threads cannot acquire the lock on the same object, but threads "associated" with other objects can execute that method without problems. Now, because I have only one thread associated with the object c1, it is anyway needed to use the synchronized method? Also if no other threads associated with the same object exist?
In your specific example, synchronized is not needed because each thread has its own instance of the class, so there is no data "sharing" between them.
If you change your example to:
Thread T1 = new Thread(c);
Thread T2 = new Thread(c);
Then you need to synchronize the method because the ++ operation is not atomic and the instance is shared between threads.
The bottom line is that your class is not thread safe without synchronized. If you never use a single instance across threads it doesn't matter. There are plenty of legitimate use cases for classes which are not thread safe. But as soon as you start sharing them between threads all bets are off (i.e. vicious bugs may appear randomly).
Given code/example does not need synchronization since it is using two distinct instances (and so, variables). But if you have one instance shared between two or more threads, synchronization is needed, despite comments stating otherwise.
Actually it is very simple to create a program to show that behavior:
removed synchronized
added code to call the method from two threads
public class SynchronizedCounter {
private int c = 0;
public void increment() {
c++;
}
public static void main(String... args) throws Exception {
var counter = new SynchronizedCounter();
var t1 = create(100_000, counter);
var t2 = create(100_000, counter);
t1.start();
t2.start();
// wait termination of both threads
t1.join();
t2.join();
System.out.println(counter.c);
}
private static Thread create(int count, SynchronizedCounter counter) {
return new Thread(() -> {
for (var i = 0; i < count; i++) {
counter.increment();
}
System.out.println(counter.c);
});
}
}
Eventually (often?) this will result in weird numbers like:
C:\TMP>java SynchronizedCounter.java
122948
136644
136644
add synchronized and output should always end with 200000:
C:\TMP>java SynchronizedCounter.java
170134
200000
200000
Apparently posted code is not complete: the incremented variable is private and there is no method to retrieve the incremented value. impossible to really know if the method must be synchronized or not.

When should I use distinct instances or shared instances across multiple threads?

The first way is this:
public class Demo {
public static void main (String args[]) {
Apple a1 = new Apple();
Apple a2 = new Apple();
Thread t1 = new Thread(a1, "First Thread");
Thread t2 = new Thread(a2, "Second Thread");
t1.start();
t2.start();
}
}
The second way is this:
public class Demo {
public static void main (String args[]) {
Apple a = new Apple();
Thread t1 = new Thread(a, "First Thread");
Thread t2 = new Thread(a, "Second Thread");
t1.start();
t2.start();
}
}
The void run() method is in Apple class and I did not paste it here.
Seems like in the first situation I created 2 Apple class objects and pass them respectively to t1 and t2. While in the 2nd situation I pass the same Apple class object to t1 and t2. What's the real difference in terms of multi-threading? Could you suggest me which way is correct and recommended? Thank you!
If your Apple object is stateless then there is no difference.
But if it has some state and its run() method modifies it properties then you need to synchronize access to those properties (or make sure that those properties are thread-safe) of an Apple object.
What to prefer depends on your business logic.
If Apple is an object which is thread-safe then it may be okay (or indeed desirable) to share it between threads. If it's not thread-safe then by using it concurrently you are creating an opportunity for race conditions and other difficult-to-diagnose bugs to occur.
Difference depends a lot on implementation of Apple class, in 1 case this might be best option while in another it might be huge mistake.
If class Apple is immutable and just exposes some data or event better if it only has pure functions which depend only on their input parameters then using same instance is desired approach.
On the other hand if class isn't made to work with multiple threads then you will definitely run into race condition problems.
It really depends on what the Apple class really does. Let's look at a sample Apple class:
public class Apple implements Runnable{
private int counter;
#Override
public void run(){
for(int i = 0; i < 10; i++){
counter += i;
}
System.out.println(counter);
}
}
Now in the first way you get prints in the console which look like the following:
45 // first thread
45 // second thread
Though in the second way it will be pretty unpredictable because now both Threads are modifying the counter variable. It could at best look like this:
45 // first thread
90 // second thread
But could also look like this:
51 // first thread
90 // second thread
In this simple example it is not a big issue. But when handling other tasks, which maybe modify files, accesses databases or anything that relies on deterministic behavior you'll get into big trouble.,

Creating and naming multiple, simultaneous threads with a for loop

Is there a way to create multiple threads that run simultaneously with a for loop? Consider this example:
for(int i = 1; i<=36; i++) {
if(new Random().nextInt(2)==0){
ActionThread nr = new ActionThread();
}
}
I don't want the threads to be killed after completion of the if statement. The end of each thread is randomly determined in the ActionThread class itself. Also, how do I name the threads automatically? For example, instead of nr, the first thread should be named nr1, the second nr2, the third nr3, and so on.
I'm assuming that ActionThread is some custom class that you have created that extends Thread.
I don't want the threads to be killed after completion of the if statement.
They won't be. However, it doesn't look like you have started them yet. Read the javadocs for Thread. Read the material at the top, then look at the start() and run() methods.
If you don't start a thread ... nothing happens.
Also, if you want some other part of your application to be able to "do things" to the threads once they have been created, you should replace the nr local variable with a data structure that the the rest of the application can get at; e.g. a list or an array.
(It is also possible to find extant threads via the ThreadGroup tree, but it is complicated.)
Also, how do I name the threads automatically?
Call Thread.setName(), or pass the thread name to the (relevant) Thread constructor. For example:
nr.setName("thr" + i);
Or you could even make your ActionThread set its own name in the constructor.
I should also point out that is is generally considered to be a bad idea to create subclasses of Thread. It is better to put your thread logic into a custom Runnable class, then create and pass a Runnable instance as a Thread construct argument. Like this:
public class MyRunnable implements Runnable {
#Override
public void run() {
// thread logic goes here
}
}
Thread th = new Thread(new MyRunnable());
th.start();
If you want to pass parameters to the thread logic, add a constructor to your runnable class with some arguments, and provide them when you instantiate the runnable.
Why do it this way? Because it allows you to easily change your code to use a thread loop or executor or some such.
public static void main(String[] a) {
List<ActionThread> threads = new ArrayList<>();
for (int i = 1; i <= 36; i++) {
if (new Random().nextInt(2) == 0) { // no idea why you have put this
// but seems unecessary
ActionThread thread = new ActionThread();
threads.add(thread);
thread.start();
}
}
}
class ActionThread extends Thread {
#Override
public void run() {
// Write what to do in Thread here
}
}
Once the list of ActionThread is there you have handle to all the Threads that you have created. using threads.get(index). From question its appears that by name you meant handle to Thread instance
For automatic naming, may be use static field (counter) in ActionThread and increment him in the constructor, before generate thread name.
class ActionThread extend Thread {
private static int id = 0;
ActionThread() {
setName(String.format("n%d", ++id);
}
}

Java Threads yield method query

I am practising threads, I used yield(), iam expecting output as below: (BUT not getting as expected)
One1
Two1
One2
Two2
One3
Two3
.
.
.
.
Whats wrong in my below code?
public class Main2 {
public static void main(String[] args) {
MyThread myThread1 = new MyThread("One");
MyThread myThread2 = new MyThread("Two");
/*Thread t1 = new Thread(myThread1);
Thread t2 = new Thread(myThread2);
t1.start();
t2.start();*/
myThread1.start();
myThread2.start();
}
}
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run(){
for(int i=1;i<=20;i++) {
System.out.println(name+i);
yield();
}
}
}
and also I would like to know does commented statements correct to use or not? I mean below:
Thread t1 = new Thread(myThread1);
Thread t2 = new Thread(myThread2);
t1.start();
t2.start();
Waiting for your replies..
The yield() method clearly states in its javadoc that it is
A hint to the scheduler that the current thread is willing to yield
its current use of a processor. The scheduler is free to ignore this
hint.
As such, you can't always expect execution to pass to another thread. There is no guarantee.
Also, in your question does commented statements correct to use or not, no, it won't change anything. The Thread constructor accepts a Runnable argument on which it will eventually execute the run() method. The Thread class implements Runnable and is therefore a valid argument, but it has the same effect as if you had started the Thread itself.
If you extend thread, you do it the way you have. If you implements Runnable, you do it the commented way. Either way is fine.
Note that yield is really just a recommendation, so the order of your output is not determined. You need to use locks or another technique if you want it to always be that certain way.
Thread#yield states that
Causes the currently executing thread object to temporarily pause and allow other threads to execute.
So you won't get expected output here.
If you want expected output use wait() and notify() methods with proper synchronization.
I would like to know does commented statements correct to use or not?
Yes this is 100% valid java syntax.

Using ThreadLocal in tandem with Volatile gives unpredictable results

I was reading through Java Memory model and was playing with volatile. I wanted to check how Volatile will work in tandem with ThreadLocal. As per definition ThreadLocal has its own, independently initialized copy of the variable whereas when you use volatile keyword then JVM guarantees that all writes and subsequent reads are done directly from the memory. Based on the high level definitions i knew what i was trying to do will give unpredictable results. But just out of curiosity wanted to ask if someone can explain in more details as if what is going on in the background. Here is my code for your reference...
public class MyMainClass {
public static void main(String[] args) throws InterruptedException {
ThreadLocal<MyClass> local = new ThreadLocal<>();
local.set(new MyClass());
for(int i=0;i<5; i++){
Thread thread = new Thread(local.get());
thread.start();
}
}
}
public class MyClass implements Runnable {
private volatile boolean flag = false;
public void printNameTillFlagIsSet(){
if(!flag)
System.out.println("Flag is on for : " + Thread.currentThread().getName());
else
System.out.println("Flag is off for : " + Thread.currentThread().getName());
}
#Override
public void run() {
printNameTillFlagIsSet();
this.flag = true;
}
}
In your code you create a ThreadLocal reference as a local variable of your main method. You then store an instance of MyClass in it and then give that same reference of MyClass to 5 threads created in the main method.
The resulting output of the program is unpredictable since the threads are not synchronized against each other. At least one thread will see the flag as false the other four could see the flag as either true or false depending on how the thread execution is scheduled by the OS. It is possible that all 5 threads could see the flag as false, or 1 could see it false and 4 see it true or anything in between.
The use of a ThreadLocal has no impact on this run at all based on the way you are using it.
As most have pointed out you have deeply misunderstood ThreadLocal. This is how I would write it to be more accurate.
public class MyMainClass {
private static final ThreadLocal<MyClass> local = new ThreadLocal<>(){
public MyClass initialValue(){
return new MyClass();
}
}
public static void main(String[] args) throws InterruptedException {
local.set(new MyClass());
for(int i=0;i<5; i++){
Thread thread = new Thread(new Runnable(){
public void run(){
local.get().printNameTillFlagIsSet();
local.get().run();
local.get().printNameTillFlagIsSet();
}
});
thread.start();
}
}
}
So here five different instances of MyClass are created. Each thread will have their own accessible copy of each MyClass. That is Thread created at i = 0 will always have a different instance of MyClass then i = 1,2,3,4 despite how many local.get() are done.
The inner workings are a bit complicated but it can be done similar to
ConcurrentMap<Long,Thread> threadLocalMap =...;
public MyClass get(){
long id = Thread.currentThread().getId();
MyClass value = threadLocalMap.get(id);
if(value == null){
value = initialValue();
threadLocalMap.put(id,value);
}
return value;
}
To further answer your question about the volatile field. It is in essence useless here. Since the field itself is 'thread-local' there will be no ordering/memory issues that can occur.
Just don't divinize the JVM. ThreadLocal is a regular class. Inside it uses a map from current thread ID into an object instance. So that the same ThreadLocal variable could have its own value for each thread. That's all. Your variable exists only in the main thread, so it doesn't make any sence.
The volatile is something about java code optimization, It just stops all possible optimizations which allow avoid redundant memory reads/writes and execution sequence re-orderings. It is important for expecting some particular behaviour in multi-threaded environment.
You have two big problems:
1) As many pointed out, you are not using ThreadLocal properly so you don't actually have any "thread local" variables.
2) Your code is equivalent to:
MyClass someInstance = new Class();
for (...)
... new Thread(someInstance);
so you should expect to see 1 on and 4 off. However your code is badly synchronized, so you get random results. The problem is that although you declare flag as volatile, this is not enough for good synchronization since you do the check on flag in printNameTillFlagSet and then change the flag value just after that method call in run. There is a gap here where many threads can see the flag as true. You should check the flag value and change it within a synchronized block.
You main thread where you have a ThreadLocal object is being passed to all the threads. So the same instance is being passed.
So its as good as
new Thread(new MyClass());
What you could try is have an object being called by different threads with a thread local variable. This will be a proper test for ThreadLocal where each thread will get its own instance of the variable.

Categories

Resources