Is there a mistake at 9:57? Should it say the this.framesTakenCount is being read from main memory, not this.framesStoredCount (which is what the diagram says). Is that correct or am I misunderstanding?
Hi Joe. Actually, both this.framesStoredCount and this.framesTakenCount will be read from main memory at that time... but you might be right it should say this.framesTakenCount there.
@@JakobJenkov also in your example public Frame takeFrame() { while (!hasNewFrame) { // busy wait until new frame arrives } Frame newFrame = this.frame; this.framesTakenCount++; this.hasNewFrame = false; return newFrame; } can these two instructions be parallely executed Frame newFrame = this.frame; this.framesTakenCount++;
Sir , you are a genius at this , internet is filled with just basics of threading but this is exactly what I was looking for , Thank you a lot for the amazing explanation.
volatile gurantee even if only 1 variable is volatile is not at all know to me in all these years. Thanks a lot for doing that and clarifying it soo nicely and very clearly
00:02 Java Happens Before Guarantee and Instruction Restriction 03:12 Instruction reordering can affect multi-threaded applications 06:41 Java volatile keyword ensures visibility of changes made by one thread to another 10:09 Volatile variables need to be flushed to main memory 13:19 Instruction reordering can break visibility guarantees of volatile variables 16:34 Java has challenges with instruction reordering and visibility 19:47 Instruction reordering around synchronized blocks may break visibility guarantees. 23:01 Java happens before guarantees ensure correct communication between threads. Crafted by Merlin AI.
Hey Jakob! Thanks for the awesome video. Can you please point references to: "Furthermore, all the variables visible to the thread reading the volatile variable will also have their values refreshed from main memory." ? Thanks!
What do you mean with "references"? Like a link to a text explaining it? I got this info from here: " anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f" www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html Yes, there are a few more restrictions on which variables become visible for a thread after reading a volatile filed f, but the general principle as illustrated in the example in the video should hold up!
Nice and concise explanation. Thanks ! Happens before relationship has been explained so good ! In my experience, writing a concurrent code with mutable data shared across multiple threads is quite challenging . And perhaps this is one of the reasons that functional programming is gaining trust among the programmers. As functional paradigm promotes and facilitates immutable data so it allows the users to write thread safe code in much simpler way . Just to let you know ,the conciseness and to the point explanations of your articles is one the reasons that have quite extensively used your Blogs in past to prepare for my interviews :)
Hi Vishal, thanks for the feedback! I prefer the "no shared state" concurrency model to the "functional parallelism" model. It's simpler, does not require immutability, can be tuned more etc.
@@JakobJenkov If it comes to the application where every millisecond matters then yes, I agree with you. It is good to have the thread and variable tweaking power in developer's (skilled) hand. :)
I'm really impressed with that great explanation and the way you simplify things with the graphs and code samples! Thank you for putting all that effort! BTW IF You Didn't Have a Profile Picture I Would Have thought This is LORD BEALISH speaking😂
:-D ... Lord Baelish :-D ... well, not quite ;-) ... more like Ragnar Lodbrok ;-) :-D (... as I am Danish too ;-) ). Thank you for your kind words about the video! :-)
i just want confirmation just correct if i am right or wrong basically whatever happens the subsequent write before the write of the volatile variable should be read after the volatile read right?? and secondly if we set the volatile write first before the non-volatile writes the data we get during the read will be stale and then the updated data becomes available after next call but that data is old data for the other threads after the writes since these writes have not been update before the volatile writes right ?????
synchronized and volatile both are providing visibility guarantee. Can you please explain more about the volatile ? my assumption is if volatile always update the value at main memory, why it can't be able to solve the problem of an earlier program, the problem of 2,000,000 count value?
Reply I have a seperate tutorial about the Java volatile keyword that explains this here: ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-nhYIEqt-jvY.html Basically the problem is, that performing an incrementation ( variable++ ) is done by first reading the volatile variable from memory into a CPU register, incrementing it, and writing it directly back to main memory. However, another thread could be reading the variable from main memory too, right after the first thread read it - but before the first thread wrote the incremented value back to main memory. Thus, if the value in main memory was 15, both threads read the value 15 from main memory, increment their local copies to 16, and both write 16 back to main memory. The correct result should of course have been 17 - after 2 threads incremented the value.
This is great. To me, the part of the guarantee surrounding synchronized seems to be obvious, or it would make the whole point of locking the object a joke, so I was just nodding my head there, that of course it has to happen. But the guarantees around volatile and their implications seem anything but obvious to me. Great video.
True - with the happens before guarantee - locking to avoid race conditions would not really work - because you would have no functional visibility guarantee.
I had to read it many times myself the first time I started studying the happens before guarantee. It's not easy to understand. There are still details around it I am not sure I understand fully yet (such as what "variables visible to the thread" means 100% precisely).
@Jakob JenKov First think i want to say is "thank you" so much for threading Video's . i have learnt lots of things from your video and text material. please keep it up good work. do you know any best book for threading?
Ok!! I need to wrap my head around these words of wisdom!! Why my Java Teacher never taught me all these in classes? So well explained. Watching a video like this inspires me to realise about the connection between the every piece of code we write and the hardware underneath!!
Hi Vikash, yes, the more you understand about how the Java code is executed by the underlying hardware, the more efficient code you can write! Not just within concurrency, but also in terms of raw single-threaded performance! Check out my video about False Sharing in Java for an example of concurrent performance drops / gains that most people might not be aware of!
The explanations are very detailed, but I don't know any reading sources that can help you understand it like that, on the internet I only see very sketchy explanations and I really don't understand the essence of it.
You are welcome! And yes, I try to make my videos "to the point" - yet going somewhat deeply into the topic so that people understand more deeply what is going on.
God of Concurency..i have bene flowing you since my 2014 when you used to write blog post only...by going through your post i attend interview like a LION when they ask mutithreading qns.......Thanks a Lot form 10+ yrs exp guy from BLR,India.
The section @7:04 "The visibility guarantee of volatile variables" can also be re-written/re-titled as "Volatile happens before guarantee" where "happens before" relation means if action (store frame) of Thread 1 happens before action (take frame) of Thread 2, it should be visibile to Thread 2 , hence happens before relations exists there between two different actions of different Threads. So "Visibility Guarantee of Volatile" is another form of "Happens before relationship" and the most important one as it avoids memory consistencies errors by different threads. I get the @14:10 Volatile happens before guarantee, the case there is Happens before relations is defined for two actions of Same thread.
Thank you :-) I am happy my videos help you! :-) ... I try my best, but it is not always easy to figure out "how" to best explain a given topic. I am happy when it seems I have found a good way :-)
@@JakobJenkov The way you diagram, step by step, along with the code have been extremely helpful for me. You provide a concrete learning tool to abstract ideas, and this supports my learning style.
I read "Java Concurrency in Practice" and it does cover the main topics of concurrency pretty well, but I do not remember reading about the "Happens Before Guarantee". I suspect that it is because the authors do not recommend relying on such guarantees as they are difficult to reason about. The simplest way is to be explicit and declare volatile or include in synchronised blocks all the variables that need such a thread safety requirement. I think "Java Concurrency in Practice" is a good resource and it will give a good idea of some good practices and ways of thinking about concurrency in Java and in general.
So you are saying that public void set(Values v) { synchronized (this) { this.a = v.a; this.b = v.b; this.c = v.c; } } nothing will be moved to be after ending of synchronised, but what about the following public void set(Values v) { this.c = v.c; synchronized (this) { this.a = v.a; this.b = v.b; } } What if this happens? This can be a potential issue
I don't think anything before the end of a synchronized block can be moved to after the end of a synchronized block. But, it's better to be safe than sorry, so move it inside the block if you are uncertain.
Hello! Thank for a god video. I`d recommend you to paste important statements to a screen. I mean guarantees in this context. This can help to understand concepts clearly and refer to them. Also, visibility guarantees exact formulae seem missing. TY
Thank you for the feedback! It's hard to fit all the information for a complex topic into a video in the most optimal way - so all ideas are welcome. I cannot always promise I will use them - but it's nice to see them. Gives me as broad a set of ideas to draw from as possible.
08:25 - java volatile visibility guarantee. "All the variables that are visible to the thread writing to the volatile variable will also get flushed to main memory." What does visible mean in this context? All the objects which the thread has reference to? Or just the fields of the actual object?
I have not actually been able to find a clear explanation of what *exactly* "visible to the thread" means. I assume it must be at least all local variables in the method being executed, as well as instance variables of the object that method belongs to. But I don't know if the "visibility to the thread" extends up the call stack to the methods and objects further up (the "method that called the method" etc where the thread enters / exists a synchronized block).
Hmm... I have not been diving too much into Garbage Collection. Whenever I need high performance, I design to avoid garbage collection all-together. It's called GC free design.
I did not follow why Thread 2 would loop not loop forever if we define at least one of the variables there to be volatile. Wouldnt flushing happen regardless at some point, and at which point it would be visible to Thread 2 and therefore would take it out of the while loop?
Flushing of variables stored in the caches to main memory is not guaranteed for non-volatile variables. However, due to cache coherrence strategies, CPUs can see what is stored in the other caches. What is needed is flushing of variables from CPU registers to RAM - which will first push ot to the cache, and then it is visible to the other CPUs.
How about watching the video on 1.5 speed then? It's hard to get into reasonable detail in a reasonably concise way - by using a more "chatty" style of video. They may feel more natural - more dynamic - but they are usually much longer than they need to be, and give less details than what I would normally be looking for.
I have some here (link below). Note: There are more examples in the src folder than what are currently listed in the README page. github.com/jjenkov/java-examples
The only comment I have on this, which is fascinating (I watched it twice!) is a combination of subtle English wording concern and pedagogical issues. There is a caption or two that is showing what could happen in a Universe without the Java Happens Before Guarantee. This caption or captions uses the word "may". Because our Universe has the Java Happens Before Guarantee (Boy, I hope almost nobody is still using Java 4? Crosses fingers) I would label the slides "could happen if we didn't have the guarantee" or something. There is a subtle difference between "may" and "could", the latter being conditional on something that may not in fact be true. I could ask Isaac Newton if he agreed, *if* he were still alive or Ouija boards actually worked. I may find you understand what I mean, if I wrote clearly enough. The "could" sometimes implies alternate timeline or reality, while "may" is still hopefully true as we write it (but may be not). When I first watched the video, I got all nervous when we were showing bad things that could happen in the world without guarantees, which could never happen in the world of modern current Java or even pretty old ones like 5, because I saw the word "may" and my mind got all nervous. I don't think English is your only/first language, and this is subtle, but I really did freak myself out the first time I watched it, with doubts about whether the guarantee was going to turn out to be conditional on some other variable in the Universe or not. Re-reading the text version, I am thinking that "re-ordering WOULD break the guarantee, so therefore that re-ordering won't happen" is the clearest way to phrase it. The way some people learn, putting an incorrect intermediate idea in their head while they are learning it can be counter-productive, they might flash back to it later even tho you showed the truth/right way shortly afterwards. I know that has happened to me in the past.
I appreciate the feedback! Precise communication is always challenging. Remember, even if you as a native English speaker "may" be aware of the subtle differences of "could" and "may" etc. - most of the viewers of this video will not be native English speakers, and thus they "may" not have the same perception of these words as you do. I am an example of exactly that - since I am not a native English speaker myself, and I chose the words that are used in the video. Even many native English speakers have problems with their own language, in terms of grammar, meaning of words etc. You may use different terms, phrases in the US, UK, Ireland, Scotland, Australia etc. to describe the same concept. People of different ages and different language skills will have different perceptions of words, and different vocabularies. Therefore - "perfect" communication does not exist in my opinion. You can try to get as close as possible, but you will never hit everyone with the same piece of information. I have been blogging for 15 years now, and there is always a corner of the material that could be a little bit better. However, I don't think it's possible to reach "perfect", as the last details of what constitutes "perfect" are quite often subjective - depending on the reader's language level, educational level, technical level etc. What is hard to understand for a beginner is often easier for a veteran. I have often myself returned to books that I once found hard to understand, and found them easier to understand the second and third time around. I phrase the happens before guarantee as : "A set of restrictions on instruction reordering to prevent instruction reordering from breaking the visibility guarantees". I don't think that is hard to understand. Because we have the happens before guarantee, no instruction reordering will take place which will break the visibility guarantees. You understood that too - even if you had to watch the video 2 times before you were certain what I meant. I have books I have read 5 times before I finally understood it all. That's normal. You have more capacity to understand the smaller, more advanced details the second and third time around. Now - from the sound of your feedback it sounds like you already know a lot of this material already, and are mostly poking around to see if it could get even better :-) ... or - that's how I perceive it. Unfortunately, "editing" a video is not possible on RU-vid. You have to replace it with a completely new version (which gets a new URL). Otherwise I would probably have updated my RU-vid videos as often as I update my website.
@@JakobJenkov might be some more jvm behind-the-scene/internals or more in depth multithreading stuff. Performance questions/ best practices to implement things avoiding common/unclear pitfalls. These are just first things that came into my mind
Wow your series are awesome, thank you. I just have one simple question: is the main memory the heap? I watched the previous video so I’m sorry if it should already have been clear to me, but since I’m under exam pressure I get confused easily ;)
@@JakobJenkov And "Local CPU registers" corresponding to a frame in the VM stack? I guess a thread corresponding to a method, and the runnable instance wrapping the run() method can be viewed as a local variable in the run() method? Thanks for your great video! Looking forward to your reply ^_^
What a fabulous lecture ! Thank you for sharing your knowledge and greetings from a fan in China! By the way, at 21:10 you said "at least not until the next time thread 1 exits this synchronized block" but you said earlier that when thread 1 enter the block, it will refresh the variables that are visible to it. So is there a scenario that valC would be modified in method set() and then restore from memory and keep going...... ?
This playlist is GOLD! I'd rather spend 8 hours doing the whole playlist and understanding stuff in depth (maybe forgetting the reasoning long-term) over watching 2 hours of surface-level explanation! Thank you for your efforts! One question though: Is there a cost to making all relevant variables volatile? That'd be much easier than making sure of the order or guarantees.
On second thought - I think the cost is unnecessary flushes to main memory so if I have all 4 vars volatile and update one after the other, there are 4 flushes to memory which could have been avoided same goes for read, multiple reads from main memory
Ok. I'm kind of confused. Visibility problem that you described in previous video, is not the same with what your saying here. Visibility problem in part 1, was when thread 1 made changes in its local copy, and before it manages to pass those changes down to main memory or the Cache. Thread 2 might have read the member variable again from main memory or Cache and thus miss the update of thread 1. It was never said or implied that threads just read the main memory once and then only read the variables from there local copies. What is the point of sharing the same instance of an Object between threads, if they're just going to use there own private copies anyways. So in this example, where you say that thread 2 will get stack in a while loop, if we don't use Volatile variables or Synchronized blocks, doesn't fit with what we've learned in part 1. Based on part 1, thread 2 will lose a bunch of frames at best, and the only way to make it stack in the while loop, is if we actually have 2 different instances of FrameExchanger, not a single shared instance. So can you please clarify what you mean by visibility problem once more. You even mention it here as well. tutorials.jenkov.com/java-concurrency/volatile.html#:~:text=The%20problem%20with%20threads%20not,not%20visible%20to%20other%20threads. Visibility problem, means that a thread can't see the LATEST UPDATES of another thread. Not that they can't see the updates at all, because they just read once from main memory, and then only use there local copies.
Both statements are true. Without using either a volatile variable, or a synchronized block around access to a variable, you have no guarantee about when a thread will write a changed variable back to main memory. It might happen for every change, or only every nth change. The Java VM makes no guarantees about when that update happens. This lack of guarantee also means that thread 2 may miss many updates from thread 1 to a given variable, for 2 reasons: A) Thread 1 may not have written the update back to main memory B) Thread 2 may not read the value from main memory If you need such guarantees (and you often - but not always - do), you need to use volatile variables or access the variables from within a synchronized block (or guarded e.g. by a Lock or similar mechanism that provides the same semantics with regards to memory synchronization).
Thanks :-) ... I have a book I had to read 4 times before I understood it all, and a 5th time before I remembered most of it :-) I often have to watch or read material several times before I finally understand it all. It's like I can read a certain amount, and then it needs some time to "sink in". Then, and only then can my brain continue with the next portion :-) I used to think maybe I wasn't as good or fast a learner as others, but now I have just accepted that this is my process. I need to read and repeat to learn!
Hi Jakob, amazing videos!! thank you for sharing your knowledge. I have a question, in the previous video "Java memory model" you mention that the primitives live in the threadstack but in this video seems they live also in the main memory (main stack). Is my understanding correct?
Local variables live on the threadstack. If a local variable points to an object, the reference (pointer) lives on the thread stack, but the object itself lives on the heap.
Great video, although I think that I'm missing something - how is it guaranteed that each method will be taken by a specific, different thread when using volatile? I get it when we use synchronize, since it puts a lock on that specific object's method, but I can't figure the logic with volatile. Thanks in advance for this great material !
Hi Jacob! Can you clarify this: You told that at the time of entering synchronized block, thread will refresh values of visible variables (I guess ValueExchanger fields?) from Main Memory. But how would it work for code from your tutorial: public void set(Values v) { this.valA = v.valA; this.valB = v.valB; synchronized(this) { this.valC = v.valC; } } As I understand, after entering synchronized block here, thread should update all A,B,C fields. But how would refresh work for fields A,B? Wouldn't then changes that happen before synchronized block be replaced with values retrieved from Main Memory?
When entering the synchronized block all visible values will be refreshed from main memory. However, v.valA and v.valB will NOT be copied into this.valA and this.valB again - until next time the assignments are executed.