class Clstest{
public static String testStaticMethod(String inFileStr) {
// section 0
// section 1
// do something with inFileStr
// section 2
// section 3
return inFileStr;
}
}
Let's assume there are five threads are each executing a call to Clstest.testStaticMethod("arg-n") at the same time.
Thread 1 calls Clstest.testStaticMethod("arg-1").
When thread 1 is in the section 1, thread 2 calls Clstest.testStaticMethod("arg-2").
Then what will happen to Thread 1? Will it go to sleep state?
When Thread 1 got the chance will it resume the execution from section 1 where it was paused?
How it happens when there's one Clstest.testStaticMethod and same Clstest.testStaticMethod is shared between all five threads?
Is there any possibility to interchange the inFileStr sent by multiple threads?
Hans Passant's answer is good. But I thought I would try and explain at a slightly more simple level for anybody who comes across this and is newish to Java. Here goes..
Memory in java is split up into two kinds - the heap and the stacks. The heap is where all the objects live and the stacks are where the threads do their work. Each thread has its own stack and can't access each others stacks. Each thread also has a pointer into the code which points to the bit of code they're currently running.
When a thread starts running a new method it saves the arguments and local variables in that method on its own stack. Some of these values might be pointers to objects on the heap. If two threads are running the same method at the same time they will both have their code pointers pointing at that method and have their own copies of arguments and local variables on their stacks. They will only interfere with each other if the things on their stacks point to the same objects on the heap. In which case all sorts of things might happen. But as Hans points out, Strings are immutable (cannot be changed) so we're safe if this is the only object being "shared".
So many threads can be running the same method. They might not be running at the same time - it depends how many cores you have on your machine as the JVM maps Java threads to OS threads, which are scheduled onto hardware threads. You therefore have little control over the way these threads interleave without using complex synchronisation mechanisms.
Note that sleeping is something a thread does to itself.
Will it go to sleep state?
No, running a thread does not affect other threads as long as they don't intentionally synchronize with each other. If you have more than one processor core, all recent machines do, those threads are likely to execute at the exact same time. That gets to be bit less likely when you start 5 threads since your machine might not have enough cores. The operating system is forced to choose between them, giving them each some time to run. The job of the thread scheduler. A thread will then not be in a "sleep" state, it is simply paused and waiting for the thread scheduler to give it a chance to run. It will resume where it was interrupted by the scheduler.
Is there any possibility to interchange the inFileStr sent by multiple threads?
There is no such possibility, threads have their own stack so any method argument and local variable will be unique for each thread. Using a string furthermore guarantees that these threads cannot interfere with each other since strings are immutable.
There's no such guarantee if the argument is a reference to another kind of mutable object. Or if the method itself uses variables that are static or references to objects on the heap. Synchronization is required when a thread modifies the object and another thread reads it. The lock keyword in the C# language is the boilerplate way to implement such required synchronization. The fact that the method is static does not mean such synchronization is never required. Just less likely since you don't have to worry about threads accessing the same object (sharing this).
Related
One of the first things we all learnt about concurrency in Java is that we use locks (synchronized keyword, Lock/ReadWriteLock interface) to protect against concurrent access. For example:
synchronized void eat(){
//some code
}
In theory, this method eat() can be executed by a single thread. Even though there are many threads waiting to execute it, only one will take the lock. But then comes parallelism, which made me think twice about what I just said.
I have 4 core CPU. That means I can do 4 tasks parallelly. Yes, lock can be taken by a single thread. But could it happen that 4 threads call method eat() and take a lock at the LITERALLY same time, although there is a lock that needs to be acquired to actually do anything?
Can something like that even happen in Java? I guess it can't but I had to ask this. And how is it even dealing with a case I just said?
...4 threads...take a lock at the LITERALLY same time...
Can't happen. Any "synchronized" operation (e.g., "take a lock") must operate on the system's main memory, and in any conventional computer system, there is only one memory bus. It is physically impossible for more than one CPU to access the main memory at the same time.
If two CPUs decide to access the memory at literally the same time, the hardware guarantees that one of them will "win" the race and go first, while the other one is forced to wait its turn.
Short answer - JVM keeps a list of threads that are trying to get the lock.
More details
https://wiki.openjdk.java.net/display/HotSpot/Synchronization
Also, worth mentioning that list (aka "inflated lock") is only created when really required (== when contention on a lock happens).
I'm reading a book called "Java Concurrency In Practice" and in the first chapter the following code is demonstrated as thread unsafe
public class UnsafeSequence {
private int value;
/** Returns a unique value. */
public int getNext() {
return value++;
}
}
So if two threads run this code we can get unwanted results because they will interchange in different steps such as reading, modifying and writing the value. Is this determined only by OS, or do threads switch between each other on different "bytecode commands" for example? Is there any way to know all possible places where threads might switch from one to another, not just for this code but in general?
As several comments note, no. Two things you can do:
Write your classes in a thread-safe manner, so that thread scheduling isn't an issue.
Use concurrency support to prevent issues.
Keep reading the book.
Is there any way to know all possible places where threads might switch from one to another, not just for this code but in general?
This question is a bit vagiue. Let me split it up in two parts:
Two threads can wander over the same piece of code and happily interleave, except:
inside atomic operations (including complex operations inside of thread-safe classes)
inside guarded blocks (e.g. using a synchronized block, lock, semaphore, or some other memory fence)
Threads can switch all the time, which is 100% up to the OS. In theory a thread might even never get a chance to be 'scheduled in' again if the OS decides so. Threads may die spuriously (e.g. killed in ProcessExplorer). You never know when a thread will be stopped in it's tracks (suspended), but you do know that if it happens inside an atomic operation, no other thread will enter that code until the suspended thread resumes and completes the operation.
It happens whenever the system scheduler feels like. It has nothing to do with the JVM if the JVM only passes that scheduling to the native processor.
I would like to ask you about how internally Spring Singleton will work in concurrency software. Please use as many details as you know. I want to know deply how JVM is resolve that.
I find similar question here - however that one concer two separate methods invoked by two separate thread - here I have one method and two threads
#Component
public class SpringSingleton {
public void justWait(){
try {
Thread.sleep(5000);
}
catch(InterruptedException ex) {}
}
}
#Component
public class StartClass {
#Autowired
private SpringSingleton singleton;
public void runAfterAppStart(){
for(int i=0; i<=1; i++){
CompletableFuture.runAsync(() -> singleton.justWait());
}
}
}
After running these piece of code, you'll see that two threads are end at almost same time.
How it is possible? Why Thread2 doesn't have to wait until Thread1 will finish his work?
As I understand whole flow, instance of SpringSingleton class will be placed on JVM Heap, then on stack Java will place two threads (Thread1,Thread2). Each of thread will contains own (independant) reference to Spring Singleton class - now...
Thread1 will use his reference to execute method "justWait". These method is obviously some instructions for processor. So if these instructions are currently processes - how Thread2 is able to invoke them?
The only explanation for me is, JVM will somehow copy byte code from heap to each thread - then everythink is clear - but it is really happening here?
Thank you for explanation of that problem. Even buzzwords which I can google will be really helpful
How it is possible? Why Thread2 doesn't have to wait until Thread1 will finish his work?
Because you don't have any synchronisation going on.
The only explanation for me is, JVM will somehow copy byte code from heap to each thread - then everythink is clear - but it is really happening here?
You're mixing up two things: instance variables and bytecode. Bytecode is the compiled Java code, and is present only once, and not on the heap. Instance variables are created on the heap, but each thread will have its own set.
In this example, however, there aren't any instance variables. So each thread simply runs the same bytecode. There is no need to wait, because bytecode doesn't change after it's been loaded.
Your question is not related to Spring Singleton implementation.
There are 3 threads. One main thread and 2 CompletableFuture threads. Main thread creates completable futures, finish it's work and application exits. It doesn't wait for the CompletableFuture to complete.
You can check this by adding additional Thread.sleep(10000) after the loop, for example:
public void runAfterAppStart(){
for(int i=0; i<=1; i++){
CompletableFuture.runAsync(() -> singleton.justWait());
}
// Hold main thread for the CompletableFuture to complete.
Thread.sleep(10000);
}
Why Thread2 doesn't have to wait until Thread1 will finish his work?
Because threads are specifically made to do not wait one another.
If you want one thread to wait until another completes use synchronized method or block.
Singleton methods are re-entrant, because actual code is in the class object.
Even if there are two non-singleton objects, still there is only one instance of code in the class.
When object(bean) is a singleton it means there is only one instance of that class and assigned memory for its data - instance variables.
The only explanation for me is, JVM will somehow copy byte code from heap to each thread
it is wrong
BTW: in real there is no such thing as "simultaneously" it is just a matter of nanoseconds between thread switching...
I can help with your last couple paragraphs--
There is just 1 copy of the code but both threads are able to run through it at the same time. It's possible that both cores of a cpu are running through the code at EXACTLY the same time, but each CPU points to different data so that the exact same code might operate on different data.
In fact, one CPU may have data that evaluates to "true" another might evaluate to "false" so that an if() statement causes the threads to diverge.
The problem is there aren't enough CPUs so we have a way to save and restore the state of a single CPU so that it can act like multiple CPUs to a certain extent--each of these virtual CPUs is a thread.
Since they can save their state, a single CPU can run thousands of threads at (seemingly) the same time by stopping and restarting them thousands of times a second.
The short of it is that it's just one copy of the code but different data for each thread.
So far what I have understood about wait() and yield () methods is that yield() is called when the thread is not carrying out any task and lets the CPU execute some other thread. wait() is used when some thread is put on hold and usually used in the concept of synchronization. However, I fail to understand the difference in their functionality and i'm not sure if what I have understood is right or wrong. Can someone please explain the difference between them(apart from the package they are present in).
aren't they both doing the same task - waiting so that other threads can execute?
Not even close, because yield() does not wait for anything.
Every thread can be in one of a number of different states: Running means that the thread is actually running on a CPU, Runnable means that nothing is preventing the thread from running except, maybe the availability of a CPU for it to run on. All of the other states can be lumped into a category called blocked. A blocked thread is a thread that is waiting for something to happen before it can become runnable.
The operating system preempts running threads on a regular basis: Every so often (between 10 times per second and 100 times per second on most operating systems) the OS tags each running thread and says, "your turn is up, go to the back of the run queue' (i.e., change state from running to runnable). Then it lets whatever thread is at the head of the run queue use that CPU (i.e., become running again).
When your program calls Thread.yield(), it's saying to the operating system, "I still have work to do, but it might not be as important as the work that some other thread is doing. Please send me to the back of the run queue right now." If there is an available CPU for the thread to run on though, then it effectively will just keep running (i.e., the yield() call will immediately return).
When your program calls foobar.wait() on the other hand, it's saying to the operating system, "Block me until some other thread calls foobar.notify().
Yielding was first implemented on non-preemptive operating systems and, in non-preemptive threading libraries. On a computer with only one CPU, the only way that more than one thread ever got to run was when the threads explicitly yielded to one another.
Yielding also was useful for busy waiting. That's where a thread waits for something to happen by sitting in a tight loop, testing the same condition over and over again. If the condition depended on some other thread to do some work, the waiting thread would yield() each time around the loop in order to let the other thread do its work.
Now that we have preemption and multiprocessor systems and libraries that provide us with higher-level synchronization objects, there is basically no reason why an application programs would need to call yield() anymore.
wait is for waiting on a condition. This might not jump into the eye when looking at the method as it is entirely up to you to define what kind of condition it is. But the API tries to force you to use it correctly by requiring that you own the monitor of the object on which you are waiting, which is necessary for a correct condition check in a multi-threaded environment.
So a correct use of wait looks like:
synchronized(object) {
while( ! /* your defined condition */)
object.wait();
/* execute other critical actions if needed */
}
And it must be paired with another thread executing code like:
synchronized(object) {
/* make your defined condition true */)
object.notify();
}
In contrast Thread.yield() is just a hint that your thread might release the CPU at this point of time. It’s not specified whether it actually does anything and, regardless of whether the CPU has been released or not, it has no impact on the semantics in respect to the memory model. In other words, it does not create any relationship to other threads which would be required for accessing shared variables correctly.
For example the following loop accessing sharedVariable (which is not declared volatile) might run forever without ever noticing updates made by other threads:
while(sharedVariable != expectedValue) Thread.yield();
While Thread.yield might help other threads to run (they will run anyway on most systems), it does not enforce re-reading the value of sharedVariable from the shared memory. Thus, without other constructs enforcing memory visibility, e.g. decaring sharedVariable as volatile, this loop is broken.
The first difference is that yield() is a Thread method , wait() is at the origins Object method inheritid in thread as for all classes , that in the shape, in the background (using java doc)
wait()
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
yield()
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.
and here you can see the difference between yield() and wait()
Yield(): When a running thread is stopped to give its space to another thread with a high priority, this is called Yield.Here the running thread changes to runnable thread.
Wait(): A thread is waiting to get resources from a thread to continue its execution.
This is a very conceptual question.
Let's say I have 2 separate threads. Thread A continually gets the time and stores it as a variable, and thread B continually gets the time from thread B's variable and does something with it.
The moment thread B accesses the variable in thread A, does thread A stop running until the operation is finished?
To expand, what if you had 3 threads, Thread A to get the current time and set it as a variable in Thread B, And then thread C to read the variable.
If Thread A is in the middle of assigning the variable the moment thread C comes to read it, does thread stop running until A is finished?
Thanks for the great answers, but now I have 1 more question. If they would interfere, what is the preferred solution to make the multiple threads not compete when communicating. (Conceptually) what would you do to make it so these threads could share the value of the variable while remaining as fast as possible individually?
Memory and thrads are two entirely different things. Even a variable that is part of a class which represents a thread is just memory like any other that any thread can access.
However, what complicates this and does in fact cause a slowdown is processor caches: in order for two threads running on different CPUs to access the same piece of memory and "see" each other's changes, the CPU caches have to be synchronized, which can completely negate the (massive) speed advantages of these caches if it happens a lot.
Note that because of caches, thread B may actually see an outdated value of the variable for an arbitrarily long time unless both access the variable within a synchronized block, or the variable is declared with the keyword volatile.
No normally not unless you declare the getter and the setter synchronized. If i.e. the setter is being called from one thread and another thread wants to access the getter it has to wait for the other thread to end his task first.
I hope I understood the question right.
It won't make thread B slow thread A down.
But:
1. Thread A may slow thread B down. Depending on the system architecture (cores and caches), every write by thread A will purge the cache line from thread B's CPU. B's next read will be more expensive.
2. If you use a lock to protect the data structure, both threads have to obtain it. Then, obviously, thread A will slow down.
3. If you don't use a lock, and your data type isn't atomic, you may read corrupt data. For example, if the time changes from 0x0000ffff to 0x00010000, you may read 0x0001ffff. Normally, an integer, which is aligned on 4 bytes, is atomic, so if your time is time_t you're probably OK. But the details are platform dependent.
It depends on the OS and the number of CPU, but basically yes, when one thread is working, the other waits. It doesn't matter much if thread B uses a variable used by thread A, as they share the same memory.
Yes they slow down.
And that's because your concurrency checks you coded in the application: since you have a lock, semaphore, monitor, or whatever, to regulate the access to the stored variable, each thread will possibly wait to gain exclusive access to read/write the variable.
and even if you don't have concurrency checks i am pretty sure that memory doesn't allow simultaneous reads or read/write: since this situation might happen, your threads will be forced to slow down a little bit nevertheless