Lesson: Ultimate Java Part 3: Concurrency and Multithreading -The Volatile Keyword video.
I use SDK Jetbrains Runtime Version 17.0.9 with the Language Level “17 - sealed types, always strict floating-point semantics” in IntelliJ Idea Community Edition.
ISSUES:
- The
incrementTotalBytes()
method in “The volatile keyword” lesson does not increment theTotalBytes()
field in the “for loop” within the DownloadFileTask class which is invoked bythread1
. - The
synchronized
keyword does not synchronize access to theisDone
field so thatthread2
can run and exit successfully.
To recap: the totalBytes
field is not updated, and thread2
does not exits.
I have re-watched numerous times all the videos in the Concurrency module and concluded that all my code is syntactically identical to Mosh’s code.
After careful analysis, I am left with these questions:
- When does
thread1
send the interrupt indication for the code in the DownloadFileTask class to validateif (Thread.currentThread().isInterrupted()) return;
in the overwrittenrun();
method? - If
isDone = true
, when doeswhile (!status.isDone()){}
becomefalse
? There are no methods to change the value ofisDone
.
These aspects of the code in the lesson do not make sense to me. I cannot find a logical answer to these questions. I cannot help but think that there are lines of code missing that should address these questions within the lesson, and yet Mosh’s code works in the video (not in my IDE).
Here is my code for your review, I will include my code for the three classes (DownloadStatus, DownloadFileTask, and ThreadDemo) so that you can help me understand where the errors lie, please. I have renamed the DownloadStatus class to “VolatileKeyWordDemo”, otherwise my code is identical to the lessons’ code.:
- VolatileKeyWordDemo:
Summary
public class VolatileKeyWordDemo {
private boolean isDone;
private int totalBytes;
private int totalFiles;
private final Object totalBytesLock = new Object();
private final Object totalFilesLock = new Object();
public void incrementTotalBytes(){
synchronized (totalBytesLock){
totalBytes++;}}
public void incrementTotalFiles(){
synchronized (totalFilesLock){
totalFiles++;}}
public int getTotalBytes() {
return totalBytes;}
public int getTotalFiles() {
return totalFiles;}
public synchronized boolean isDone() {
return isDone;
}
public synchronized void done() {
isDone = true;
}
}// End of VolatileKeyWordDemo
- DownloadFileTask:
Summary
public class DownloadFileTask implements Runnable {
private VolatileKeyWordDemo status;
public DownloadFileTask(VolatileKeyWordDemo status) {
this.status = new VolatileKeyWordDemo();}
@Override
public void run () {
System.out.println("Downloading a File: " + Thread.currentThread().getName());
for (var i = 0; i < 1_000_000; i++) {
if (Thread.currentThread().isInterrupted()) return;
status.incrementTotalBytes();}
status.done();
System.out.println();
System.out.println("Download Complete: " + Thread.currentThread().getName() + " ");
}
}// End of DownloadStatusDemo
- ThreadDemo:
Summary
public class ThreadDemo {
public static void show() {
var status = new VolatileKeyWordDemo();
var thread1 = new Thread(new DownloadFileTask(status));
var thread2 = new Thread(() -> {
System.out.println("Thread: " + Thread.currentThread().getName() +" has started.");
while (!status.isDone()) {}
System.out.println(status.getTotalBytes());}
);
thread1.start();
thread2.start();}
public static void main(String[] args){
show();}
}// End of ThreadDemo
This is the output of my program after I manually stop it:
Downloading a File: Thread-0
Thread: Thread-1 has started.Download Complete: Thread-0
Process finished with exit code 130 (interrupted by signal 2: SIGINT)
Any suggestions will be greatly appreciated.