1 00:00:05,000 --> 00:00:11,000 Hello, today, we're going to have interesting lesson, you know, sometimes it happens and the topics 2 00:00:11,000 --> 00:00:17,000 that I need to explain it, but they're either too small for a separate lesson or highly connected with 3 00:00:17,000 --> 00:00:17,000 other topics. 4 00:00:18,000 --> 00:00:22,000 That's why a group such topics and decided to put them in one lesson. 5 00:00:22,000 --> 00:00:27,000 We'll start from understanding of memory management in Java and just writing programs. 6 00:00:27,000 --> 00:00:32,000 This will give you information about how data is managed by different threats. 7 00:00:32,000 --> 00:00:36,000 It is also important to understand hardware, memory, architecture. 8 00:00:36,000 --> 00:00:42,000 It is a different from general memory model, but your memory model works with hardware memory and is 9 00:00:42,000 --> 00:00:43,000 built on top of it. 10 00:00:44,000 --> 00:00:50,000 That's why software engineers, we need to understand how all this is connected, learns this information. 11 00:00:50,000 --> 00:00:56,000 It will be easier for you to understand volatile keywords and how it works in various lessons. 12 00:00:56,000 --> 00:01:01,000 We already talked about atomic operations and I mentioned that there are generally two concurrent atomic 13 00:01:01,000 --> 00:01:05,000 package that contains types that supports atomic operations. 14 00:01:05,000 --> 00:01:11,000 In this letter, we'll review this package at the end of the and will want to read local variables are. 15 00:01:12,000 --> 00:01:17,000 I will also share with you some use cases when you might need to use read local, but it will be up 16 00:01:17,000 --> 00:01:22,000 to you how to use this to also talk about inheritable local. 17 00:01:22,000 --> 00:01:24,000 And I will show you examples. 18 00:01:24,000 --> 00:01:25,000 Let's start. 19 00:01:25,000 --> 00:01:31,000 And before we start learning to read local, volatile and other concepts, let's understand first memory 20 00:01:31,000 --> 00:01:37,000 management and how Seurat's use in memory, why it is important for us, because we need to know and 21 00:01:37,000 --> 00:01:43,000 understand when different threads can use values, return to shared variables by Osas threats and how 22 00:01:43,000 --> 00:01:46,000 to synchronize access to shared variables when necessary. 23 00:01:46,000 --> 00:01:52,000 When I have multiple threats, Dunam divides memories between stress tests and the hit their separate 24 00:01:52,000 --> 00:01:53,000 stack for each threat. 25 00:01:53,000 --> 00:01:55,000 And you can see the visualizations a slide. 26 00:01:55,000 --> 00:01:57,000 What is stored in threat stack? 27 00:01:58,000 --> 00:02:03,000 If you remember less lesson about a memory module from my Java course, you might guess what is stored 28 00:02:03,000 --> 00:02:09,000 in old stack of each threat is information about mass that we invoke from the threat or local variables 29 00:02:09,000 --> 00:02:11,000 for each must have been executed. 30 00:02:12,000 --> 00:02:16,000 Local variables created in the threat obviously are not visible to all of us. 31 00:02:16,000 --> 00:02:22,000 Let's hope you remember that if memory stores, objects, objects are instances of all reference types 32 00:02:22,000 --> 00:02:23,000 that we know. 33 00:02:23,000 --> 00:02:29,000 And it doesn't matter if an object was created as a threat and assigned to a local variable, or even 34 00:02:29,000 --> 00:02:35,000 if it is created as a member variable of another object, the object is still stored in the hip, but 35 00:02:35,000 --> 00:02:39,000 the references to these objects are stored in threads stack. 36 00:02:40,000 --> 00:02:43,000 Let's look at more detailed version of previous life here. 37 00:02:43,000 --> 00:02:48,000 You can see where information about local variables and objects is stored. 38 00:02:48,000 --> 00:02:49,000 So nothing new to you. 39 00:02:49,000 --> 00:02:52,000 In case you are familiar with Java memory module. 40 00:02:52,000 --> 00:02:58,000 Also important thing to highlight here that the variable may be of primitive and reference type variable 41 00:02:58,000 --> 00:03:05,000 of primitive type contains value in itself and completely stored in threat stack in case variable has 42 00:03:05,000 --> 00:03:06,000 reference time. 43 00:03:06,000 --> 00:03:13,000 In this case, a reference to the heap is stored in stack memory and object is stored in the memory. 44 00:03:13,000 --> 00:03:15,000 What about static variables? 45 00:03:15,000 --> 00:03:20,000 Take into account static variables don't belong to any object, but belong to class itself. 46 00:03:21,000 --> 00:03:24,000 They are stored in the memory along with the class definition. 47 00:03:25,000 --> 00:03:31,000 Since Case Thread has a reference to an object, it can access object in memory using the reference 48 00:03:31,000 --> 00:03:35,000 and each side may do this in case it knows is a reference to an object. 49 00:03:36,000 --> 00:03:38,000 And now let me share a really interesting scene. 50 00:03:39,000 --> 00:03:43,000 Imagine that this column masset on the same object at the same moment of time. 51 00:03:44,000 --> 00:03:48,000 These threats, both of them will access objects, variables. 52 00:03:48,000 --> 00:03:53,000 But we have just learned the local variables are stored in a stack of each threat. 53 00:03:53,000 --> 00:04:00,000 So each threat will have its own reference to the object in the Heat and its own copy of the local variable 54 00:04:01,000 --> 00:04:05,000 that is important for understanding, for data manipulation from different threats. 55 00:04:05,000 --> 00:04:12,000 So in this case, some local variables are completely copied to each threat, and each threat has copy 56 00:04:12,000 --> 00:04:14,000 of the reference to an object in memory. 57 00:04:15,000 --> 00:04:18,000 Now let's talk about hardware, memory architecture. 58 00:04:18,000 --> 00:04:24,000 As I already mentioned in the agenda of this lesson, it is important for us to understand how hardware 59 00:04:24,000 --> 00:04:28,000 memory is architected because general memory model is built on top of it. 60 00:04:29,000 --> 00:04:33,000 So another computer often has to and even more in central processing units. 61 00:04:34,000 --> 00:04:36,000 That is why they're called CPU. 62 00:04:37,000 --> 00:04:38,000 What does this mean for us? 63 00:04:38,000 --> 00:04:46,000 That means that we can physically has calculations done in parallel because you can run the one thread 64 00:04:46,000 --> 00:04:47,000 at any given time. 65 00:04:48,000 --> 00:04:54,000 C.P.U contains a set of registers zis registers consider to be memory of our CPU. 66 00:04:54,000 --> 00:05:01,000 That's why you can perform operations on these registers much faster, that it can perform on variables 67 00:05:01,000 --> 00:05:02,000 in the main memory. 68 00:05:02,000 --> 00:05:07,000 Besides registers, CPU also have Sibiu cash memory. 69 00:05:07,000 --> 00:05:13,000 And again, if we were talking about performance, it's worth to say that C.P.U is able to access cash 70 00:05:13,000 --> 00:05:20,000 memory much faster than the RAM memory, but obviously not as fast as it can access internal registers. 71 00:05:21,000 --> 00:05:24,000 ROMME stands for random access memory. 72 00:05:24,000 --> 00:05:31,000 It is a form of computer memory that can be read and changed in any order typically used to store data. 73 00:05:32,000 --> 00:05:37,000 For example, you start from some room is reserved for Google. 74 00:05:37,000 --> 00:05:42,000 You start your Java app JVM reserves from memory for the Java process. 75 00:05:43,000 --> 00:05:50,000 LCP use may access around and the RAM is typically much bigger than the cache memory of the CPU's. 76 00:05:50,000 --> 00:05:54,000 Let's understand how the process of reading and writing data is happening. 77 00:05:54,000 --> 00:06:00,000 In case you need to read some data from RAM, it will read some parts of the data from RAM into the 78 00:06:00,000 --> 00:06:07,000 CPU cache and it is also possible the CPU will read some parts of the data into internal registers and 79 00:06:07,000 --> 00:06:10,000 only after that operate on that data. 80 00:06:10,000 --> 00:06:13,000 And in case you need to write, result back to RAM. 81 00:06:14,000 --> 00:06:17,000 We are going through the same route, but just in other direction. 82 00:06:18,000 --> 00:06:25,000 From CPU registers to RAM, CPU will flush the result of computation from its internal register. 83 00:06:25,000 --> 00:06:32,000 Those are cache memory and at some point the value back to the RAM eviction policy from CPU cash is 84 00:06:32,000 --> 00:06:33,000 simple. 85 00:06:33,000 --> 00:06:38,000 One memory is needed for something else, then cache memory is flashed back to zero. 86 00:06:39,000 --> 00:06:45,000 So as you can see, Java memory model and hardware memory architecture are not the same sync. 87 00:06:45,000 --> 00:06:52,000 There is no separation between stack and heap in hardware memory, but how it is connected. 88 00:06:52,000 --> 00:07:00,000 Then let me show on the next slide both stack and the heap memory allocated in ram memory that is reserved 89 00:07:00,000 --> 00:07:08,000 for Java process parts of threats stacks and he may sometimes be present in CPU caches and in internal 90 00:07:08,000 --> 00:07:09,000 SEPI registers. 91 00:07:09,000 --> 00:07:16,000 What problem may occur in case objects and variables are stored in different memory areas in the computer? 92 00:07:17,000 --> 00:07:18,000 The domain potential problems. 93 00:07:19,000 --> 00:07:25,000 There was a batch of threat updates and the second problem is there is a condition during the reading, 94 00:07:25,000 --> 00:07:27,000 checking and writing shared variables. 95 00:07:28,000 --> 00:07:31,000 Let me explain what these issues are about and details. 96 00:07:32,000 --> 00:07:34,000 The first issue is visibility of threat updates. 97 00:07:35,000 --> 00:07:38,000 Imagine that some updated copy of the variable. 98 00:07:38,000 --> 00:07:45,000 There is no guarantees that other threats will be able to see this update in case the threats has the 99 00:07:45,000 --> 00:07:46,000 reference to the same object. 100 00:07:46,000 --> 00:07:50,000 Without using proper synchronization or volatile keyword. 101 00:07:51,000 --> 00:07:58,000 There is a chance that updates to the shared object made by one threat may not be visible to NSW. 102 00:07:58,000 --> 00:07:59,000 How it may happen. 103 00:08:00,000 --> 00:08:01,000 Let's imagine the next case. 104 00:08:01,000 --> 00:08:08,000 Initially shared object is stored in RAM memory main memory and imagine the one thread that is running 105 00:08:08,000 --> 00:08:10,000 on CPU object in the state of this object. 106 00:08:11,000 --> 00:08:17,000 As long as a cache has not been flashed back to the main memory, the updated version of the shared 107 00:08:17,000 --> 00:08:22,000 object is not visible to run on other CPU's. 108 00:08:22,000 --> 00:08:23,000 Is that clear? 109 00:08:24,000 --> 00:08:31,000 This may end up that each thread contains its own version of the same variable in different CPU cache 110 00:08:31,000 --> 00:08:32,000 as slide. 111 00:08:32,000 --> 00:08:39,000 You can see how to threats update the same account variable and until CPU cache memory isn't flashed, 112 00:08:39,000 --> 00:08:43,000 these updates are sitting there to solve this issue. 113 00:08:43,000 --> 00:08:45,000 We may use volatile keyword. 114 00:08:46,000 --> 00:08:49,000 I will explain later what volatile keyword does. 115 00:08:50,000 --> 00:08:52,000 Let's discuss the second issue race conditions. 116 00:08:53,000 --> 00:08:59,000 Imagine that you have a variable account of a shared object, this variable and CPU cache of one threat 117 00:08:59,000 --> 00:09:01,000 and in CPU a cache of another threat. 118 00:09:02,000 --> 00:09:06,000 Both threats does the same thing they add the one does account. 119 00:09:06,000 --> 00:09:14,000 Variable count has been incremented two times and then this program would run sequentially and each 120 00:09:14,000 --> 00:09:16,000 threat update is a verbal one after another. 121 00:09:16,000 --> 00:09:19,000 In this case, the value of Cowens variable would be true. 122 00:09:20,000 --> 00:09:22,000 However, this is not the case. 123 00:09:22,000 --> 00:09:30,000 The increments happened concurrently and we got last update because no matter which threat update version 124 00:09:30,000 --> 00:09:36,000 of counts variable in main memory is updated, value will be overridden by another threat. 125 00:09:36,000 --> 00:09:39,000 How to solve this synchronize blocks. 126 00:09:39,000 --> 00:09:45,000 In this course you will learn how to use synchronize blocks properly to synchronize access of multiple 127 00:09:45,000 --> 00:09:47,000 threats to critical sections. 128 00:09:47,000 --> 00:09:53,000 I believe that now you understand how memory management is performed on different levels of the threat 129 00:09:53,000 --> 00:09:54,000 in programs. 130 00:09:54,000 --> 00:09:59,000 I promise you also to explain what volatile keywords is and how it works. 131 00:09:59,000 --> 00:10:02,000 As you already can understand that Dune's and. 132 00:10:02,000 --> 00:10:10,000 We should consider a lot of other things the process in flush its cash buffer in any order dude compiler 133 00:10:10,000 --> 00:10:11,000 may optimize our execution. 134 00:10:11,000 --> 00:10:17,000 We are ordering order and is an optimization technique for performance improvements. 135 00:10:17,000 --> 00:10:23,000 When you write the program, you expect instructions will be executed in order as written in the program. 136 00:10:23,000 --> 00:10:25,000 But that is not always the case. 137 00:10:25,000 --> 00:10:33,000 For example, you may declare two fields in time that is equal to 10 and JS that is equal to five. 138 00:10:33,000 --> 00:10:34,000 It might happen. 139 00:10:34,000 --> 00:10:42,000 That variable is the second one in zero will be initialized first, but I variable still wouldn't be 140 00:10:42,000 --> 00:10:51,000 initialized and has the zero value, but not then because zero is a default value for I so far. 141 00:10:51,000 --> 00:10:58,000 Non-dependent operations like initialization of course fields in some case compiler may apply some optimizations 142 00:10:58,000 --> 00:11:01,000 and the ordering is one of such techniques. 143 00:11:01,000 --> 00:11:08,000 And in case I will use volatile keywords with the fields, this will be assigned for runtime environment 144 00:11:08,000 --> 00:11:11,000 that I need predictable order for operations. 145 00:11:11,000 --> 00:11:15,000 With these variables, orderings won't be applied to such variables. 146 00:11:15,000 --> 00:11:22,000 And also I need to flash any updates to these variables instantly to make updates visible to all other 147 00:11:22,000 --> 00:11:22,000 threats. 148 00:11:22,000 --> 00:11:27,000 Does it make sense to explain how volatile works and why do we need it? 149 00:11:27,000 --> 00:11:34,000 I had to explain your hardware, memory architecture and Java memory model, but now I believe it is 150 00:11:34,000 --> 00:11:38,000 crystal clear what problem we are trying to solve by adding volatile keywords. 151 00:11:38,000 --> 00:11:45,000 And now when I break, huge means that you would find in the Internet and in volatile Keever, it doesn't 152 00:11:45,000 --> 00:11:49,000 mean that all operations with such variable will be atomic. 153 00:11:50,000 --> 00:11:57,000 You may find statements in Internet and sometimes even on stack overflow that volatile variables behave 154 00:11:57,000 --> 00:11:59,000 like atomic and operations. 155 00:11:59,000 --> 00:12:00,000 That is not true. 156 00:12:01,000 --> 00:12:06,000 The effect of volatile keywords is that approximately each individual read or write. 157 00:12:06,000 --> 00:12:11,000 A separation on that variable is made atomically visible to all threads. 158 00:12:12,000 --> 00:12:14,000 However, operations is. 159 00:12:14,000 --> 00:12:21,000 It requires more than one redivide cycle, such as incremented, for example, will not be executed 160 00:12:21,000 --> 00:12:29,000 as atomic because we need read value of the variable at one safe result of calculation and assign that 161 00:12:29,000 --> 00:12:35,000 this variable Z separation's one V atomic, even if you will work with volatile variable. 162 00:12:36,000 --> 00:12:42,000 Remember that only atomic operations I Stipe's from Java to concurrent atomic package. 163 00:12:43,000 --> 00:12:46,000 We talked about these atomic types for a long time already. 164 00:12:47,000 --> 00:12:51,000 Let me show them how to work with these types, first of all. 165 00:12:51,000 --> 00:12:57,000 And as always, I recommended to start from the official documentation from Oracle, from documentation. 166 00:12:57,000 --> 00:13:04,000 We see that this package is a small tool kit of classes that support locally safe programming on single 167 00:13:04,000 --> 00:13:04,000 variables. 168 00:13:05,000 --> 00:13:07,000 Here you can find class summary. 169 00:13:08,000 --> 00:13:13,000 It is easy to remember these class names because most of them have atomic at the beginning. 170 00:13:14,000 --> 00:13:17,000 Atomic Boulin Atomic Integer atomic bomb. 171 00:13:17,000 --> 00:13:21,000 I bet you can understand what type of values these atomic types. 172 00:13:21,000 --> 00:13:28,000 Berquist Atomic Reference is a type that describes an object reference that may be updated atomically. 173 00:13:29,000 --> 00:13:34,000 Each of these types provide its own API to perform necessary operations. 174 00:13:34,000 --> 00:13:41,000 Also that types to execute threats, safe operations with arrays, atomic integer array, atomic clock 175 00:13:41,000 --> 00:13:49,000 array, atomic reference and the even more times, for example, double atter, you can use this type 176 00:13:49,000 --> 00:13:49,000 to perform. 177 00:13:49,000 --> 00:13:51,000 Swed safe addition of double's. 178 00:13:52,000 --> 00:13:56,000 Let's jump to the code examples and I'll show you how to work with the Stipe's. 179 00:13:57,000 --> 00:14:03,000 For example, here is a code that creates 10000 threats and update counter variable Baycol increment 180 00:14:03,000 --> 00:14:05,000 massive protection. 181 00:14:05,000 --> 00:14:11,000 That increment method is not a synchronized one and they also don't have any synchronized blocks here. 182 00:14:11,000 --> 00:14:16,000 But this code is safe and the security from animal to certain issues. 183 00:14:17,000 --> 00:14:17,000 Why? 184 00:14:18,000 --> 00:14:25,000 Because my counter has type atomic integer that supports safe operations in increments. 185 00:14:25,000 --> 00:14:32,000 Masset, I use API of atomic integer done in case and is incremental value I can use is I get an increment 186 00:14:32,000 --> 00:14:35,000 or increment and get these. 187 00:14:35,000 --> 00:14:43,000 Tomas's are logically difference in terms of what value you want to get before or after an increment. 188 00:14:43,000 --> 00:14:48,000 Let's run this example and in console you will always find ten thousand. 189 00:14:48,000 --> 00:14:54,000 That is because during increment operation as a threat, we're not able to update the counter variable 190 00:14:54,000 --> 00:14:55,000 in parallel. 191 00:14:55,000 --> 00:14:57,000 Let me open the source code of this time. 192 00:14:58,000 --> 00:15:02,000 If you look at S1, you would find that the. 193 00:15:02,000 --> 00:15:10,000 Plenty of useful assets, some of them are get and set masses get and add as a single operation if you 194 00:15:10,000 --> 00:15:18,000 want to, some integer values also their atomic decrements, decrements and get and get in command and 195 00:15:18,000 --> 00:15:22,000 the masses to convert atomic integer to as a primitive times. 196 00:15:22,000 --> 00:15:26,000 The rest of the atomic rubber stamps work pretty similar. 197 00:15:26,000 --> 00:15:31,000 And as always, in case of any questions, feel free to leave your question and comments below this 198 00:15:31,000 --> 00:15:32,000 here. 199 00:15:32,000 --> 00:15:34,000 And the last but not the least. 200 00:15:34,000 --> 00:15:37,000 What I'd like to share with you for today is a thread local. 201 00:15:37,000 --> 00:15:40,000 I have separate file was named for local demo. 202 00:15:40,000 --> 00:15:45,000 But before we jump to an example, let's understand a little bit more about Fred. 203 00:15:45,000 --> 00:15:46,000 Local time. 204 00:15:47,000 --> 00:15:50,000 So local is a tribe that is declared in Java land package. 205 00:15:51,000 --> 00:15:55,000 That means you don't need any additional income statements to start using. 206 00:15:55,000 --> 00:16:02,000 This type of local allows us to store data that will be accessible only by a single one. 207 00:16:02,000 --> 00:16:03,000 You might need this. 208 00:16:03,000 --> 00:16:09,000 There might be cases where you don't want the threats, interact with the data of other threats and 209 00:16:09,000 --> 00:16:17,000 adjusted the variables of local type differ from their normal counterparts in that each thread that 210 00:16:17,000 --> 00:16:23,000 accesses one has its own independently initialized copy of the variable spread. 211 00:16:23,000 --> 00:16:29,000 Local instances are typically private static fields and classes that we often associate state with a 212 00:16:29,000 --> 00:16:35,000 threat, for example, a user, a yi or transactionally, something very specific to one single threat. 213 00:16:36,000 --> 00:16:38,000 Now let's start with the practical part. 214 00:16:38,000 --> 00:16:41,000 I declare a private static field of threat. 215 00:16:41,000 --> 00:16:49,000 Local type parametrized by string threat local will be similar to wrapper you get and set object of 216 00:16:49,000 --> 00:16:51,000 parametrized type into it. 217 00:16:51,000 --> 00:16:57,000 You can just create an instance of certain local types like you usually do with all of the reference 218 00:16:57,000 --> 00:16:57,000 types. 219 00:16:57,000 --> 00:17:04,000 With the help of your keywords, you can also use static Masset with initial zaftig supplier as method 220 00:17:04,000 --> 00:17:07,000 argument to initialize the variable. 221 00:17:07,000 --> 00:17:12,000 If you're not familiar with lambda expressions and supplier type, I recommend it to pass my functional 222 00:17:12,000 --> 00:17:14,000 programming course for Java engineers. 223 00:17:15,000 --> 00:17:21,000 There are a lot of examples that will explain the topic of lambda expressions and functional interfaces. 224 00:17:21,000 --> 00:17:27,000 Let's move on for the sake of the demo and to make it as simple as possible, I will keep my thread 225 00:17:27,000 --> 00:17:32,000 local parametrized by integer type and I will create object with new keyword. 226 00:17:33,000 --> 00:17:35,000 After that I implement Runnable interface. 227 00:17:35,000 --> 00:17:41,000 In this time, in run unmastered, I set random value from zero to one hundred does a transaction I 228 00:17:42,000 --> 00:17:43,000 with the local variable. 229 00:17:43,000 --> 00:17:46,000 After that I made my sleep for one second. 230 00:17:47,000 --> 00:17:49,000 I am doing this for the sake of the demo. 231 00:17:49,000 --> 00:17:56,000 During one second we can guarantee that both threads will be started and it is one hundred percent assurance 232 00:17:56,000 --> 00:17:59,000 that this set method will be involved in one. 233 00:18:00,000 --> 00:18:03,000 And then as a threat, I have to sleep in one second. 234 00:18:03,000 --> 00:18:07,000 I print the value of thread local to cancel all threads. 235 00:18:07,000 --> 00:18:12,000 Technically, I need to create threads, objects and start them and pay attention. 236 00:18:12,000 --> 00:18:19,000 Transaction ID is a static variable and we may assume that it exists in single copy, but both threads 237 00:18:19,000 --> 00:18:22,000 will have different values associated with this variable. 238 00:18:23,000 --> 00:18:24,000 Don't believe me. 239 00:18:24,000 --> 00:18:27,000 Let's run the program after one second pause. 240 00:18:27,000 --> 00:18:28,000 I see. 241 00:18:28,000 --> 00:18:32,000 And so the two threads print printed different values of the same static variable. 242 00:18:33,000 --> 00:18:39,000 How this has happened, you can imagine the thread local is a map in this map. 243 00:18:39,000 --> 00:18:45,000 This thread is a key and the value is the values that we set our thread local variable. 244 00:18:45,000 --> 00:18:50,000 And when I get value, I just extract that using the key mussarat object. 245 00:18:51,000 --> 00:18:52,000 That's why you shouldn't. 246 00:18:52,000 --> 00:18:55,000 Or is it another stretchable access value from another thread? 247 00:18:56,000 --> 00:19:00,000 And that values that you said in one thread will be our written in other thread. 248 00:19:01,000 --> 00:19:03,000 And one more thing related to thread local. 249 00:19:03,000 --> 00:19:06,000 We have another type that extends throughout local. 250 00:19:06,000 --> 00:19:08,000 It is inheritable Sareb local. 251 00:19:09,000 --> 00:19:10,000 What is the difference? 252 00:19:10,000 --> 00:19:17,000 Instead of each thread having its own value inside the local is inheritable spread local grants, access 253 00:19:17,000 --> 00:19:22,000 to RELISTOR threat and all child threats created by the threat. 254 00:19:22,000 --> 00:19:25,000 Let's look at the example I have read local variable. 255 00:19:26,000 --> 00:19:28,000 This is parametrized by type string. 256 00:19:28,000 --> 00:19:30,000 Nothing special here. 257 00:19:30,000 --> 00:19:33,000 And the next field has inheritable spread local time. 258 00:19:34,000 --> 00:19:36,000 I create the instance of this type with the help of you. 259 00:19:36,000 --> 00:19:40,000 Keeva, let's run this app and look at the main message. 260 00:19:40,000 --> 00:19:47,000 Now, I read the first thread and I said the local value and inheritable spread local value. 261 00:19:47,000 --> 00:19:51,000 After that, I print values that are stored inside these two variables. 262 00:19:52,000 --> 00:19:56,000 And as you can see in console, everything is straightforward here. 263 00:19:56,000 --> 00:19:59,000 I can see value of the variables after that. 264 00:19:59,000 --> 00:20:01,000 Inside this threat, I create a large. 265 00:20:01,000 --> 00:20:08,000 A threat, this threat is a child's threat and the values of state, local and inheritable threat, 266 00:20:08,000 --> 00:20:14,000 local variables here and in Arkansas, you can see that I don't have access to the threat local variable 267 00:20:14,000 --> 00:20:17,000 on this level, but I can see inheritable threat, local value. 268 00:20:17,000 --> 00:20:21,000 And after that, I create a separate threat threat. 269 00:20:21,000 --> 00:20:24,000 Number two, I make it sleep for one second. 270 00:20:24,000 --> 00:20:29,000 And after that, I want to bring the values of threat local and inheritable threat local. 271 00:20:30,000 --> 00:20:36,000 And as you may already understand, the threat of local law, inheritable threat local is accessible 272 00:20:36,000 --> 00:20:37,000 from a national threat. 273 00:20:37,000 --> 00:20:39,000 Hope that this example is clear for you. 274 00:20:39,000 --> 00:20:43,000 And you know what a threat to local and what is inheritable threat local. 275 00:20:44,000 --> 00:20:46,000 Let's review what we have learned in this lesson. 276 00:20:46,000 --> 00:20:50,000 In this lesson, we learned how memory is managed in most training programs. 277 00:20:51,000 --> 00:20:56,000 Also now, you know, hardware, memory, architecture and how German memory model uses memory. 278 00:20:57,000 --> 00:21:01,000 All this let us understand whether volatile keyword and why we needed. 279 00:21:02,000 --> 00:21:09,000 After that, we performed over of two concurrent atomic package and so atomic integer example. 280 00:21:09,000 --> 00:21:14,000 And at the end of the lesson we learned to read local type and inheritable are local. 281 00:21:15,000 --> 00:21:16,000 That's it for this lesson. 282 00:21:16,000 --> 00:21:18,000 Thanks a lot for your attention. 283 00:21:18,000 --> 00:21:21,000 Have a great day and see you in the next lesson.