Hello, today, we're going to have interesting lesson, you know, sometimes it happens and the topics
that I need to explain it, but they're either too small for a separate lesson or highly connected with
other topics.
That's why a group such topics and decided to put them in one lesson.
We'll start from understanding of memory management in Java and just writing programs.
This will give you information about how data is managed by different threats.
It is also important to understand hardware, memory, architecture.
It is a different from general memory model, but your memory model works with hardware memory and is
built on top of it.
That's why software engineers, we need to understand how all this is connected, learns this information.
It will be easier for you to understand volatile keywords and how it works in various lessons.
We already talked about atomic operations and I mentioned that there are generally two concurrent atomic
package that contains types that supports atomic operations.
In this letter, we'll review this package at the end of the and will want to read local variables are.
I will also share with you some use cases when you might need to use read local, but it will be up
to you how to use this to also talk about inheritable local.
And I will show you examples.
Let's start.
And before we start learning to read local, volatile and other concepts, let's understand first memory
management and how Seurat's use in memory, why it is important for us, because we need to know and
understand when different threads can use values, return to shared variables by Osas threats and how
to synchronize access to shared variables when necessary.
When I have multiple threats, Dunam divides memories between stress tests and the hit their separate
stack for each threat.
And you can see the visualizations a slide.
What is stored in threat stack?
If you remember less lesson about a memory module from my Java course, you might guess what is stored
in old stack of each threat is information about mass that we invoke from the threat or local variables
for each must have been executed.
Local variables created in the threat obviously are not visible to all of us.
Let's hope you remember that if memory stores, objects, objects are instances of all reference types
that we know.
And it doesn't matter if an object was created as a threat and assigned to a local variable, or even
if it is created as a member variable of another object, the object is still stored in the hip, but
the references to these objects are stored in threads stack.
Let's look at more detailed version of previous life here.
You can see where information about local variables and objects is stored.
So nothing new to you.
In case you are familiar with Java memory module.
Also important thing to highlight here that the variable may be of primitive and reference type variable
of primitive type contains value in itself and completely stored in threat stack in case variable has
reference time.
In this case, a reference to the heap is stored in stack memory and object is stored in the memory.
What about static variables?
Take into account static variables don't belong to any object, but belong to class itself.
They are stored in the memory along with the class definition.
Since Case Thread has a reference to an object, it can access object in memory using the reference
and each side may do this in case it knows is a reference to an object.
And now let me share a really interesting scene.
Imagine that this column masset on the same object at the same moment of time.
These threats, both of them will access objects, variables.
But we have just learned the local variables are stored in a stack of each threat.
So each threat will have its own reference to the object in the Heat and its own copy of the local variable
that is important for understanding, for data manipulation from different threats.
So in this case, some local variables are completely copied to each threat, and each threat has copy
of the reference to an object in memory.
Now let's talk about hardware, memory architecture.
As I already mentioned in the agenda of this lesson, it is important for us to understand how hardware
memory is architected because general memory model is built on top of it.
So another computer often has to and even more in central processing units.
That is why they're called CPU.
What does this mean for us?
That means that we can physically has calculations done in parallel because you can run the one thread
at any given time.
C.P.U contains a set of registers zis registers consider to be memory of our CPU.
That's why you can perform operations on these registers much faster, that it can perform on variables
in the main memory.
Besides registers, CPU also have Sibiu cash memory.
And again, if we were talking about performance, it's worth to say that C.P.U is able to access cash
memory much faster than the RAM memory, but obviously not as fast as it can access internal registers.
ROMME stands for random access memory.
It is a form of computer memory that can be read and changed in any order typically used to store data.
For example, you start from some room is reserved for Google.
You start your Java app JVM reserves from memory for the Java process.
LCP use may access around and the RAM is typically much bigger than the cache memory of the CPU's.
Let's understand how the process of reading and writing data is happening.
In case you need to read some data from RAM, it will read some parts of the data from RAM into the
CPU cache and it is also possible the CPU will read some parts of the data into internal registers and
only after that operate on that data.
And in case you need to write, result back to RAM.
We are going through the same route, but just in other direction.
From CPU registers to RAM, CPU will flush the result of computation from its internal register.
Those are cache memory and at some point the value back to the RAM eviction policy from CPU cash is
simple.
One memory is needed for something else, then cache memory is flashed back to zero.
So as you can see, Java memory model and hardware memory architecture are not the same sync.
There is no separation between stack and heap in hardware memory, but how it is connected.
Then let me show on the next slide both stack and the heap memory allocated in ram memory that is reserved
for Java process parts of threats stacks and he may sometimes be present in CPU caches and in internal
SEPI registers.
What problem may occur in case objects and variables are stored in different memory areas in the computer?
The domain potential problems.
There was a batch of threat updates and the second problem is there is a condition during the reading,
checking and writing shared variables.
Let me explain what these issues are about and details.
The first issue is visibility of threat updates.
Imagine that some updated copy of the variable.
There is no guarantees that other threats will be able to see this update in case the threats has the
reference to the same object.
Without using proper synchronization or volatile keyword.
There is a chance that updates to the shared object made by one threat may not be visible to NSW.
How it may happen.
Let's imagine the next case.
Initially shared object is stored in RAM memory main memory and imagine the one thread that is running
on CPU object in the state of this object.
As long as a cache has not been flashed back to the main memory, the updated version of the shared
object is not visible to run on other CPU's.
Is that clear?
This may end up that each thread contains its own version of the same variable in different CPU cache
as slide.
You can see how to threats update the same account variable and until CPU cache memory isn't flashed,
these updates are sitting there to solve this issue.
We may use volatile keyword.
I will explain later what volatile keyword does.
Let's discuss the second issue race conditions.
Imagine that you have a variable account of a shared object, this variable and CPU cache of one threat
and in CPU a cache of another threat.
Both threats does the same thing they add the one does account.
Variable count has been incremented two times and then this program would run sequentially and each
threat update is a verbal one after another.
In this case, the value of Cowens variable would be true.
However, this is not the case.
The increments happened concurrently and we got last update because no matter which threat update version
of counts variable in main memory is updated, value will be overridden by another threat.
How to solve this synchronize blocks.
In this course you will learn how to use synchronize blocks properly to synchronize access of multiple
threats to critical sections.
I believe that now you understand how memory management is performed on different levels of the threat
in programs.
I promise you also to explain what volatile keywords is and how it works.
As you already can understand that Dune's and.
We should consider a lot of other things the process in flush its cash buffer in any order dude compiler
may optimize our execution.
We are ordering order and is an optimization technique for performance improvements.
When you write the program, you expect instructions will be executed in order as written in the program.
But that is not always the case.
For example, you may declare two fields in time that is equal to 10 and JS that is equal to five.
It might happen.
That variable is the second one in zero will be initialized first, but I variable still wouldn't be
initialized and has the zero value, but not then because zero is a default value for I so far.
Non-dependent operations like initialization of course fields in some case compiler may apply some optimizations
and the ordering is one of such techniques.
And in case I will use volatile keywords with the fields, this will be assigned for runtime environment
that I need predictable order for operations.
With these variables, orderings won't be applied to such variables.
And also I need to flash any updates to these variables instantly to make updates visible to all other
threats.
Does it make sense to explain how volatile works and why do we need it?
I had to explain your hardware, memory architecture and Java memory model, but now I believe it is
crystal clear what problem we are trying to solve by adding volatile keywords.
And now when I break, huge means that you would find in the Internet and in volatile Keever, it doesn't
mean that all operations with such variable will be atomic.
You may find statements in Internet and sometimes even on stack overflow that volatile variables behave
like atomic and operations.
That is not true.
The effect of volatile keywords is that approximately each individual read or write.
A separation on that variable is made atomically visible to all threads.
However, operations is.
It requires more than one redivide cycle, such as incremented, for example, will not be executed
as atomic because we need read value of the variable at one safe result of calculation and assign that
this variable Z separation's one V atomic, even if you will work with volatile variable.
Remember that only atomic operations I Stipe's from Java to concurrent atomic package.
We talked about these atomic types for a long time already.
Let me show them how to work with these types, first of all.
And as always, I recommended to start from the official documentation from Oracle, from documentation.
We see that this package is a small tool kit of classes that support locally safe programming on single
variables.
Here you can find class summary.
It is easy to remember these class names because most of them have atomic at the beginning.
Atomic Boulin Atomic Integer atomic bomb.
I bet you can understand what type of values these atomic types.
Berquist Atomic Reference is a type that describes an object reference that may be updated atomically.
Each of these types provide its own API to perform necessary operations.
Also that types to execute threats, safe operations with arrays, atomic integer array, atomic clock
array, atomic reference and the even more times, for example, double atter, you can use this type
to perform.
Swed safe addition of double's.
Let's jump to the code examples and I'll show you how to work with the Stipe's.
For example, here is a code that creates 10000 threats and update counter variable Baycol increment
massive protection.
That increment method is not a synchronized one and they also don't have any synchronized blocks here.
But this code is safe and the security from animal to certain issues.
Why?
Because my counter has type atomic integer that supports safe operations in increments.
Masset, I use API of atomic integer done in case and is incremental value I can use is I get an increment
or increment and get these.
Tomas's are logically difference in terms of what value you want to get before or after an increment.
Let's run this example and in console you will always find ten thousand.
That is because during increment operation as a threat, we're not able to update the counter variable
in parallel.
Let me open the source code of this time.
If you look at S1, you would find that the.
Plenty of useful assets, some of them are get and set masses get and add as a single operation if you
want to, some integer values also their atomic decrements, decrements and get and get in command and
the masses to convert atomic integer to as a primitive times.
The rest of the atomic rubber stamps work pretty similar.
And as always, in case of any questions, feel free to leave your question and comments below this
here.
And the last but not the least.
What I'd like to share with you for today is a thread local.
I have separate file was named for local demo.
But before we jump to an example, let's understand a little bit more about Fred.
Local time.
So local is a tribe that is declared in Java land package.
That means you don't need any additional income statements to start using.
This type of local allows us to store data that will be accessible only by a single one.
You might need this.
There might be cases where you don't want the threats, interact with the data of other threats and
adjusted the variables of local type differ from their normal counterparts in that each thread that
accesses one has its own independently initialized copy of the variable spread.
Local instances are typically private static fields and classes that we often associate state with a
threat, for example, a user, a yi or transactionally, something very specific to one single threat.
Now let's start with the practical part.
I declare a private static field of threat.
Local type parametrized by string threat local will be similar to wrapper you get and set object of
parametrized type into it.
You can just create an instance of certain local types like you usually do with all of the reference
types.
With the help of your keywords, you can also use static Masset with initial zaftig supplier as method
argument to initialize the variable.
If you're not familiar with lambda expressions and supplier type, I recommend it to pass my functional
programming course for Java engineers.
There are a lot of examples that will explain the topic of lambda expressions and functional interfaces.
Let's move on for the sake of the demo and to make it as simple as possible, I will keep my thread
local parametrized by integer type and I will create object with new keyword.
After that I implement Runnable interface.
In this time, in run unmastered, I set random value from zero to one hundred does a transaction I
with the local variable.
After that I made my sleep for one second.
I am doing this for the sake of the demo.
During one second we can guarantee that both threads will be started and it is one hundred percent assurance
that this set method will be involved in one.
And then as a threat, I have to sleep in one second.
I print the value of thread local to cancel all threads.
Technically, I need to create threads, objects and start them and pay attention.
Transaction ID is a static variable and we may assume that it exists in single copy, but both threads
will have different values associated with this variable.
Don't believe me.
Let's run the program after one second pause.
I see.
And so the two threads print printed different values of the same static variable.
How this has happened, you can imagine the thread local is a map in this map.
This thread is a key and the value is the values that we set our thread local variable.
And when I get value, I just extract that using the key mussarat object.
That's why you shouldn't.
Or is it another stretchable access value from another thread?
And that values that you said in one thread will be our written in other thread.
And one more thing related to thread local.
We have another type that extends throughout local.
It is inheritable Sareb local.
What is the difference?
Instead of each thread having its own value inside the local is inheritable spread local grants, access
to RELISTOR threat and all child threats created by the threat.
Let's look at the example I have read local variable.
This is parametrized by type string.
Nothing special here.
And the next field has inheritable spread local time.
I create the instance of this type with the help of you.
Keeva, let's run this app and look at the main message.
Now, I read the first thread and I said the local value and inheritable spread local value.
After that, I print values that are stored inside these two variables.
And as you can see in console, everything is straightforward here.
I can see value of the variables after that.
Inside this threat, I create a large.
A threat, this threat is a child's threat and the values of state, local and inheritable threat,
local variables here and in Arkansas, you can see that I don't have access to the threat local variable
on this level, but I can see inheritable threat, local value.
And after that, I create a separate threat threat.
Number two, I make it sleep for one second.
And after that, I want to bring the values of threat local and inheritable threat local.
And as you may already understand, the threat of local law, inheritable threat local is accessible
from a national threat.
Hope that this example is clear for you.
And you know what a threat to local and what is inheritable threat local.
Let's review what we have learned in this lesson.
In this lesson, we learned how memory is managed in most training programs.
Also now, you know, hardware, memory, architecture and how German memory model uses memory.
All this let us understand whether volatile keyword and why we needed.
After that, we performed over of two concurrent atomic package and so atomic integer example.
And at the end of the lesson we learned to read local type and inheritable are local.
That's it for this lesson.
Thanks a lot for your attention.
Have a great day and see you in the next lesson.