OK, maybe some very smart guy can enlighten me but I really do not understand why Codegym asks for using the Note class as lock (or the list or even any object that I create for just that locking purpose, that all should have the same result). Why not just using this as lock. That current code would not need more?
If the list and the two methods (addNote, removeNore) were static, then I could understand it without any problem. Or if at least the list was static. Then one could argue that all Note objects modify the same container. Accesses to this would have to be protected.
But here we even have instance methods. And each instance has its own list. Therefore it should be sufficient to synchronize this. Am I missing something or is there simply no reason for this requirement.
I'm going crazy, totally crazy.... crazy 🤪😜
Thank you very much my dear fellow learners.
oh, and it's that task: Link to english version of 1703
Lisa
Level 41
Why synchronizing using the Note class as lock?
Gelöst
Kommentare (10)
- Beliebt
- Neu
- Alt
Du musst angemeldet sein, um einen Kommentar schreiben zu können
Guadalupe Gagnon
10 August 2021, 16:08
This code is intended to have multiple threads accessing one Note object. The only shared resource in the class would be the notes field.
0
Lisa
10 August 2021, 16:41
Huh... I just understand one Note object and access? That'll mean... let me try to visualize things:
Note n = new Note(); (my object, got that). And then I also have two threads A and B. These little buggers are now working on the very same n (the cute honey 🥰) and invoking its methods.
If I'd synchronize now on this, then that'll mean n is used for saving the lock and that again would mean A and B are holding the lock and could access all Note methods in parallel.
If that's what you meant then I probably have understood it. Thanks for that short push in the right direction.
Ohhh, tee-hee, and nice to see you back araound here. I started already to miss your comments. Not that I started to feel lonely here without you, yes I did, partytime, yeah, yeah 🤪😜... Gua is back 😅
+1
Lisa
10 August 2021, 16:49
So it'll be correct that I'd could synchronize on any other object or the Note.class. With any other object I mean smth. like Object lock = new Object(); and I synchronize on lock. Or the notes list. If I synchronize on the list, then both threads would hold a reference to the n object but only one could hold the lock on the n.notes list?
Crazy, crazy, I hope that's correct... or I go crazy, crazy. Everything easy, easy and then I got mutexed 🤪 😜
0
Guadalupe Gagnon
10 August 2021, 17:10
This code is incomplete and I am not 100% sure how the missing piece(s) should work. Because the methods accept, as argument, an index where the note should be added/deleted, and the mechanism for ensuring the index is valid doesn't exist in the Notes class, it doesn't seem logical to have multiple threads calling those methods passing index numbers that could. Say thread A starts by adding a note at index 0, then thread B adds a note at index 1. This would be perfectly fine if threads A and B go one after the other, but if the processor switches to thread B before thread A physically reaches the synchronized block then thread B could try to add at index 1 when index 0 doesn't exist yet which would result in Exceptions.
0
Lisa
10 August 2021, 17:24
I modified the code of the Note class... simplified it. I've just left one method taking an index.
It's synchronized on this, prints the current thread and the index, wastes some time and prints again the thread name and the index.
Now I start two threads calling that method repeatedly on the same object with some delay. If both threads could enter the Notes method the output should mix up sooner or later. But it doesn't.
So here my visualization again and my try to explain the result ... the this lock does work perfectly for multiple threads working on the same object... but only if the mutex is implemented the way I imagine it to be.
First each object needs to have a lock boolean. If this (n) is locked then anyone checking for the lock can get the status. And as second implementation detail there needs to be saved somewhere who holds that lock. This is important, too. If you do not know who holds the lock, then no one can enter the locked block. You could either save that in the thread object (here we'll need some sort of collection) or again in this (n, and here a Thread variable would be enough - so I assume it is implemented this way). Either way locking this locks other threads working on the same object.
0
Lisa
10 August 2021, 17:25
So my initial question still stands. Why a class level lock. For static methods I would understand it.
Watching a movie now to get my head clear again.
0
Guadalupe Gagnon
10 August 2021, 19:13nützlich
This is how I imagine the threads would access the Note class:
When run it outputs the index each thread is on:
2 1173
1 139
fin
However, if you comment out the synchronized it will only print one. The other Thread ends on Exception, most likely some sort of concurrent modification exception. +1
Lisa
10 August 2021, 19:52
To be able to see what's happening I moved the print statements inside the synchronized blocks and then I run your code. Once with synchronization on the class and once with synchronizing on this. Both work as expected from synchronization.
If you look at my code it's doing (in theory and on a very reduced way) the same as yours. Starting two threads and these call methods in the Note class using the same Note object.
My problem however is not synchronization. The problem is why CG thinks there is lock other than on this necessary. Why shall I use notes list as lock. Two threads using the same object is not the reason. Your code and mine show that using this is perfectly OK.
Atm. I think class level locking is necessary for static methods and using lock objects does the same or you could setup nested locks if you should need that at one point.
So I'm coming to the conclusion that this coding example is just a really bad one. The entire multithreading explanation so far is somewhat superficial and incomprehensible and I'm not really happy with that.
But I'm happy that you try to help and enlighten me 😌🌈 so that i will become a super programmer in no time.
0
Guadalupe Gagnon
10 August 2021, 20:23Lösung
If I am following you correctly, you do ask waaaay more technical questions than most any other user, you are wondering why to use the "notes" array for the lock as opposed to "this" or "Note.class".
On this task, because of its size and scope, you could technically use anything as the lock and the results would be exactly the same. It does make logical sense to use that field as the lock because the notes List is the only shared resource being used by these 2 methods.
Using a class lock wouldn't make sense because if you had multiple independent Note objects with different threads operating on them, when one thread enters any of the synchronized blocks it would effectively lock them all.
While they don't appear in this task code, synchronized methods could be included in the Note class (which could very well be added in the real world), and using "this" to lock the synch block would also lock those methods. Those methods may not even use the "notes" List and therefor not need to be locked when the list is being accessed. That reminds me of the Vector class, which was over coded to be thread safe. Every operation was synchronized whether or not it was needed. It ends up being quite the performance hog because of this.
+2
Lisa
10 August 2021, 21:31
If I am following you correctly, you do ask waaaay more technical questions than most any other user, you are wondering why to use the "notes" array for the lock as opposed to "this" or "Note.class".
Yup, that's exactly my question. And I tested using all three lock types an all three worked as I expected them to do
Using a class lock wouldn't make sense because if you had multiple independent Note objects with different threads operating on them, when one thread enters any of the synchronized blocks it would effectively lock them all..
This is some excellent information. So locking on class level effectively will allow just one thread inside the 'class'. And that even if all threads use different instances of that class. That pretty much renders multithreading useless and once you need class level locking one should probably rethink the code structure (despite some exceptions like one of the following tasks, a synchronized singleton - but even here are better solutions existing like an inner class holding the instance field, lazy loading and thread save).
It does make logical sense to use that field as the lock because the notes List is the only shared resource
So I understood this correctly, locking on this or on notes is pretty much exchangeable here. It just looks a little bit more logically to us humans if we lock on the shared resource.
Pahh, man, confusing confusing... but you're my little gem in here 💎
0