-
Notifications
You must be signed in to change notification settings - Fork 0
Understanding β Concurrency, Threading, Synchronization
Devrath edited this page Feb 11, 2024
·
14 revisions
- A thread is defined at the operating system level
- It is defined as a set of instructions
- A process consists of a pool of threads
- Different threads can be executed at the same time
-
Ex:
JVM itself works with several threads, Such as Garbage-Collector(GC) and Just-In-Time(JIT) compiler
![Screenshot 2024-02-01 at 6 23 55β―PM](https://private-user-images.githubusercontent.com/1456191/301510218-905ab274-e0f6-415e-8629-fe09c51553eb.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg4OTQwMjEsIm5iZiI6MTczODg5MzcyMSwicGF0aCI6Ii8xNDU2MTkxLzMwMTUxMDIxOC05MDVhYjI3NC1lMGY2LTQxNWUtODYyOS1mZTA5YzUxNTUzZWIucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMDdUMDIwMjAxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9NTIyMDE3OTRjYzY4YjMyMjZhNDhkNzQ3ZTdiYzUzMjYzYjg1MzQ0OThjN2QzOTYyYTE5YTA3OTQ3OTQ5MTI0OSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.8JZSz4rOoGwPY28ms9szOEEmzj_ssL_6vR0QZPWgLog)
- Consider you are writing the document and at the same time Spell check is run for the words that are written, and the print command might be invoked and you might also receive the email.
![Screenshot 2024-02-01 at 7 29 31β―PM](https://private-user-images.githubusercontent.com/1456191/301530414-d8c19ea8-b7c1-4d32-96f3-1bf237d89dfa.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg4OTQwMjEsIm5iZiI6MTczODg5MzcyMSwicGF0aCI6Ii8xNDU2MTkxLzMwMTUzMDQxNC1kOGMxOWVhOC1iN2MxLTRkMzItOTZmMy0xYmYyMzdkODlkZmEucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMDdUMDIwMjAxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9YWQ4ZmE0ZGViMjZiOWYxOWI3ZjFmOTk2YmY5NDliM2ZiYzlmNmIwYmExNzJhNzFkYmJlNTM5OTNmMTEzYTUwNCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.crEPoZkrWFJr77Dh4MqQozoy7qre0ccYATOHp-eI4sY)
- You can observe that in a single core, actions are performed one after another synchronously, But since the actions take place so fast(ex: 5ms, 10ms), For the user it gives the feeling that all actions are happening at the same time.
![Screenshot 2024-02-01 at 7 42 17β―PM](https://private-user-images.githubusercontent.com/1456191/301532325-311c9970-86cc-4a5b-a652-ca5a0e96acbe.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzg4OTQwMjEsIm5iZiI6MTczODg5MzcyMSwicGF0aCI6Ii8xNDU2MTkxLzMwMTUzMjMyNS0zMTFjOTk3MC04NmNjLTRhNWItYTY1Mi1jYTVhMGU5NmFjYmUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI1MDIwNyUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMDdUMDIwMjAxWiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9ZmFjYTcyMWQ4MDU3ZDc3MDA2OWQxYzdmZGEwNGE1OTFmYzk3NDM4ZTMyMTAzOTMwZGE5NTdmOTNhZWQ4MDQ0MCZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.oGIHXf0hAAHe3W0ooL3UNrUpPpvG7M2561upDvqeEVk)
- In the multi-core, as you can observe multiple actions are happening at the same time distributed among two cores
- So, On a multi-core CPU, actually things are happening at the same time :)
Single Code |
Multi Code |
---|---|
![]() |
![]() |
-
Multi-threading
means multiple multiple threads running in an application. -
Thread
is like a CPU running your application. - Thus multi-threaded applications are like separate parts of the CPU running your application simultaneously.
- Why
multi-threading
is needed- Better utilization of a single CPU
- Better utilization of multiple CPUs or CPU cores.
- Better user experience about responsiveness.
- Better user experience about fairness.
Concurrent-Execution |
Parallel-Execution |
Parallel-Concurrent-Execution |
---|---|---|
![]() |
![]() |
![]() |
- Concurrency refers to how a single CPU can make progress on multiple tasks seemingly at the same time (AKA concurrently).
- Parallelism, on the other hand, is related to how an application can parallelize the execution of a single task - typically by splitting the task up into subtasks that can be completed in parallel.
- CPU-SCHEDULER is responsible for dividing the timeline of the CPU tasks in the cores
- Three reasons for the scheduler to pause the thread
- CPU should be shared equally among the threads.
- The thread is waiting for more data(Thread doing Ip/Op , Reading/Writing).
- The thread is waiting for another thread to perform some task.
- A race condition deals with
Accessing data concurrently
- Say 2 separate threads are trying to read and write the same variable, This will result in a race condition.
- Consider 2 threads are accessing the Singleton instance
- Say the first thread tries to access it, The control comes inside the if condition since the instance is null from the thread-1
- Before it is initialized say another thread tries to access the same Singleton instance, Now say the variable is not initialized by the first thread yet, the second thread also allows the control to enter the if condition.
- This would be the Ideal scenario of two threads accessing the same variable at this moment.
public class Singleton {
// Private static instance variable
private static Singleton instance;
// Private constructor to prevent instantiation from outside the class
private Singleton() { }
// Public method to get the singleton instance
public static Singleton getInstance() {
// Lazy initialization - create the instance if it doesn't exist
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
- Here by introducing the
synchronised
keyword, It will give a speciallock
object that contains akey
. - When a thread tries to access the synchronized block, it will take the key and enter the block of code and thus enter execution.
- Now at the same time another thread tries to access the synchronized block, since there is no key it cannot access the block since another earlier thread has not finished execution and has not returned the key to the lock.
- Now once the first thread finished the execution, it returns the key back and now the second thread can access it and can enter the execution
- This would
prevent
therace-condition
.
public static synchronized Singleton getInstance() {
// Lazy initialization - create the instance if it doesn't exist
if (instance == null) {
instance = new Singleton();
}
return instance;
}
- For the synchronization, We will need a special object that will hold onto the key.
- The key is available in the Object class in Java, So making it available to all the classes in the code.
Here the static method uses the class as the synchronization object
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
- Here we use the dedicated object as the key to the synchronized block.
- This is the best way to hold the synchronization whether we are in the static context or not.
private final Object key = new Object()
public string init(){
synchronized(key){
// Do some stuff
}
}
Hyperthreading (running multiple threads on a core at the βsameβ time) doesn't truly run them at the same time, it effectively switches between them, but with pipelining, it may seem like it's running them at the same time.
- Say there is a
Person-class
, Theperson-class
method isgetName()
. - And there are 2 instances of person
John
andSarah
. - The
getName()
issynchronized
- Now one of the threads is accessing
getName()
of theJohn
. - So when the thread accesses it, It takes the key and will be using the method.
- Now if there is a call from
getName()
ofjohn
toSarah
, This is possible since the thread that holds the key is the same thread accessing the other instance also.
- Deadlock is a situation, where
T1
holds key needed byT2
andT2
holds key needed byT1