How Thread Safety is Changing in .NET 9

  Рет қаралды 36,652

Nick Chapsas

Nick Chapsas

Күн бұрын

Get our Singleton Course for free: dometrain.com/...
Check out our new OpenTelemetry course: dometrain.com/...
Become a Patreon and get special perks: / nickchapsas
Hello, everybody. I'm Nick, and in this video, I will introduce you to a new C# type coming in .NET 9, which is how you will be doing locking and thread safety from now on.
Workshops: bit.ly/nickwor...
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: github.com/Elf...
Follow me on Twitter: / nickchapsas
Connect on LinkedIn: / nick-chapsas
Keep coding merch: keepcoding.shop
#csharp #dotnet

Пікірлер: 155
@user-zz6fk8bc8u
@user-zz6fk8bc8u Ай бұрын
The padlock at <a href="#" class="seekto" data-time="170">2:50</a> should really be non-static because static would even lock across different instances which is not needed here. Nick very likely knows that but IMHO he skipped the details saying "we don't want to allocate every time" but the behavior is completely different it's not just about allocating for each instance and allocating once.
@zpa89
@zpa89 Ай бұрын
This makes me wonder... It makes sense, but if you are going to do that, why not lock `this` instead? I think I could see issues if something else locks your class but it seems like it would generally work fine
@bodziotoja
@bodziotoja Ай бұрын
@@zpa89 Yep, you have pointed out the issue. You really do not want to lock on something someone else can lock on. Debugging this kind of problems could get really tricky.
@nocturne6320
@nocturne6320 Ай бұрын
EDIT: as @dammej pointed out, this will actually break thread safety, didn't think it through :p It could be easily solved like this: [ThreadStatic] private static object? _lock; //Use this private static object Lock => _lock ??= new(); This way you're still avoiding repeated allocations, but it still keeps it thread safe.
@zpa89
@zpa89 Ай бұрын
@@nocturne6320 repeated allocations of an empty object really aren't going to hurt you. You should avoid micro optimizations like that until you get to a point where you know you are having issues and you have run a profiler that shows you the actual allocation of that empty object is a noticeable bottleneck.
@martinprohn2433
@martinprohn2433 Ай бұрын
@@nocturne6320 That would not work! Consider this: Parallel creates multiple threads. All threads use Monitor.Enter to wait for other threads who are currently in the critical section. With [ThreadStatic] instead of every thread observing the same lock object, every thread would instead wait for their own lock object. This would obviously always be free. So we would end up again with with the race condition, that we started with.
@andreydeev4342
@andreydeev4342 Ай бұрын
My comment might be a bit off topic, but for some operations, including the example from video sum of integers, there is a good choice to use lock-free instructions. See Interlocked class, which allows thread-safe adding of two integers: Interlocked.Add(ref _sum, number); There is also interesting topic - compare-and-swap (CAS) algorythm, in C# it can be achieved with Interlocked.CompareExchange. There are even some lock-free thread-safe data structures (like hashtables), based on this algorythm, and maybe Nick finds it interesting to create a video on this topic.
@code8986
@code8986 11 күн бұрын
+1 for lock-free techniques
@LasseVagstherKarlsen
@LasseVagstherKarlsen Ай бұрын
<a href="#" class="seekto" data-time="465">7:45</a> Slightly incorrect about TryEnter with a timeout, the lock will not be exited if you hold it too long, the timeout specifies how long TryEnter should wait to try to grab the lock, and then fail and return false if it is unable to do so in that time. There is no mechanism that will automatically release the lock, except for whatever you write into your own code.
@billy65bob
@billy65bob Ай бұрын
Could just be an implementation detail?
@jamesreynolds3167
@jamesreynolds3167 Ай бұрын
I'd love to hear more about how SemaphoreSlim and locks work with performance comparisons. When you'd use one over the other etc. I've always preferred SemaphoreSlim, as it allows me to control how many threads can be active in a block and also still make use of async await.
@mynameisshadywhat
@mynameisshadywhat Ай бұрын
Had to double check when this video was posted <a href="#" class="seekto" data-time="285">4:45</a> you say C# 9 instead of .NET 9 😂
@AL12rs
@AL12rs Ай бұрын
I'd love to hear more about best practices and libraries for Async locking
@modernkennnern
@modernkennnern Ай бұрын
There's some talk about `await lock` similar to `await foreach` to allow asynchronous locking
@hellowill
@hellowill 11 күн бұрын
locks belong to threads so async lock doesn't really make sense IMO. Should be a semaphore.
@configadd
@configadd Ай бұрын
Still don't understand what problem the new approach solves? Its syntax has not changed much, and it also does not support asynchronous calls. What difference does it make how much faster it is if you're going to use SemaphoreSlim instead anyway?
@Kitulous
@Kitulous Ай бұрын
not all methods are async, so locking with the Lock class may still be useful
@fusedqyou
@fusedqyou Ай бұрын
FYI, SemaphoreSlim is efficient and also uses locking in the background. The point is avoiding the need to lock a thread completely until it can continue, and for synchronous code you just use this lock.
@andersborum9267
@andersborum9267 Ай бұрын
A key difference here is that you're allocading a ref struct instead of an object (i.e. the reference used in the lock() statement); also, the Lock type facilitates a number of different implementations that the Monitor type doesn't. I haven't moved to .NET 9 yet, but am keen on checking out the new API. In any case, for most developers, using the traditional approach is just fine for the majority of cases, yet retaining the ability to refactor for more modern types later.
@duffscs
@duffscs Ай бұрын
Mutex and semaphore require an os. (Not supported by browser, as anoted in source code). Lock is available on every platform even wasm, so they are getting ahead for wasm2 and multithreading operation support
@georgepagotelis
@georgepagotelis Ай бұрын
Especially since if you enable true in the project file couldn't it just improve the code if it's the same?
@YukonianOrangutangInSpace
@YukonianOrangutangInSpace Ай бұрын
Very informative, thank you! Excited for this.
@leowong9885
@leowong9885 Ай бұрын
Brings back memory of intro class to OS - mutex, p & v, monitor, critical session... Thanks for introducing the new lock mechanism.
@TheTim466
@TheTim466 Ай бұрын
critical section*
@julianocs87
@julianocs87 Ай бұрын
I had to check the date of the video when you mentioned C# 9 instead of .NET 9.
@silentdebugger
@silentdebugger Ай бұрын
I was really hoping the new Lock class would just work with async by default, given how many code paths are async in modern C#. Guess I was wrong.
@Tesfamichael.G
@Tesfamichael.G Ай бұрын
Thanks for the update. I have a question though. Is the topic about .NET 9 or C#9. at <a href="#" class="seekto" data-time="286">4:46</a>, recorded audio: 'starting from c# 9 ... '. I guess you mean .NET 9
@anonymous49125
@anonymous49125 Ай бұрын
for me in the first example with lock, I usually lock on the instance of the object itself (in this case the running instance of Example), rather than doing readonly and static a new object. If you have a shared static object as the lock argument, then it locks it for all Example instances, whereas locking on yourself (this instance) just locks it for you.
@code8986
@code8986 11 күн бұрын
You’re right that in this case the lock object shouldn’t have been static, but there are cases where it does need to be. In all cases, I prefer to have a dedicated lock object, but it’s not absolutely necessary.
@anonymous49125
@anonymous49125 10 күн бұрын
​@@code8986 I think that's a good preference. That said, I can't think of an instance where coordination/locking needs to be done with an external/dedicated object. If you have any suggestions at the ready, I would really appreciate your insight, because honestly, I can't think of any.
@the-niker
@the-niker Ай бұрын
I expected this to be syntactic sugar for SemaphoreSlim that integrates into lock() keyword if a specific Lock type is detected. Left sorely disappointed, the amount of code where I use a lock in non-async code vs async code is like 5%. And frankly in that case I use sync version of my SemaphoreSlim wrapper anyway just to be consistent. This smells like a feature that Microsoft made for themselves to speed up the internals.
@duffscs
@duffscs Ай бұрын
Mutex and semaphore require an os. (Not supported by browser, as anoted in source code). Lock is available on every platform even wasm, so they are getting ahead for wasm2 and multithreading operation support
@davidantolingonzalez4929
@davidantolingonzalez4929 Ай бұрын
​@@duffscsSemaphoreSlim works in Wasm
@GlebAOsokin
@GlebAOsokin Ай бұрын
I've read somewhere, that acquiring a SemaphoreSlim is ~10x slower than acquiring a simple lock...
@the-niker
@the-niker Ай бұрын
@@GlebAOsokin lock() makes sense in specific scenarios in projects that are not asynchronous in nature, in parallel processing of non-I/O-bound data and maybe in low-level networking. I write mostly web and desktop and I would always opt for fully async execution tree in such projects. To be fair I would even do a console app be fully async with some rare exceptions. I don't want synchronous lock() in my projects. Async semaphore being even 50x slower is nothing compared to multiple threads doing the spinlock dance and hogging CPU cores. For me seeing lock() is a code smell once there's even a remote possibility the execution path may need to touch any kind of I/O. Converting lock to semaphore later is not always trivial.
@GlebAOsokin
@GlebAOsokin Ай бұрын
@@the-niker Well, async lock is already a very rare thing, since you normally don't want to block on a long-running operation, to say nothing of an IO-bound one. I use locks all the time and almost never SemaphoreSlim for the same purpose (although I do have a RAII-like disposable wrapper for it just in case). So I kinda understand, why .NET team implemented it the way they did.
@vacantbill
@vacantbill Ай бұрын
Just to touch on some of the comments, it is important to understand that the same thread can re-enter in a lock however a semaphore will prevent this unless there is an available counter (please correct me ife knowledge is out of date on this). I believe this is one of the reasons await and lock don't play that well together.
@WileeRunner42
@WileeRunner42 Ай бұрын
Cool. This allows for the potential to have like an AsyncLock object or other behaviors. I do tend to write lock-free code but occasionally need a lock and then async rears its head. Then I'm back to a good old staple of my custom lock-free spin lock type of thing.
@ArcaneEye
@ArcaneEye Ай бұрын
isn't that just a semaphore?
@georgepagotelis
@georgepagotelis Ай бұрын
Thoughts on syntatic sugar should be covered by "true"? I feel like I'm be hood winked. If Span is running .NET 6-8 optimizations under the hood and other optimizations to improve speed. A new setting say "true" could ENFORCE the compiler to change the object to padLock conversion for older style code with a sledge hammer approach.
@phizc
@phizc Ай бұрын
You could use an analyzer to create an error if lock is used with anything other than a Lock object.
@_grigoryta
@_grigoryta Ай бұрын
<a href="#" class="seekto" data-time="69">1:09</a> Paralyzed loop? Didn't know programming concepts could have disabilities. What a diverse world we live in
@artemisDev
@artemisDev Ай бұрын
When there's a deadlock in your parallelized loop.
@foxgodess9
@foxgodess9 Ай бұрын
Very useful in case of third party API calls, for example if you want to get the weather data of 10 locations at a time, or 10 days weather at a time but your third party API only supports one parameter for one call, then parallelize them and get all the results. it's fun lol
@MayronDev
@MayronDev Ай бұрын
A bit confused onj the difference between Enter and EnterScope. When and why would I need to create a lock scope? Why not just lock using the object?
@nickchapsas
@nickchapsas Ай бұрын
The lock scope will be created for you on the boundaries of the lock if you lock a lock type
@chralexNET
@chralexNET Ай бұрын
I think EnterScope creates a disposable Scope-object, so that you can use the using-keyword to automatically call Exit at the end of the scope. There may be more to it though, so best to read the official documentation.
@shanehebert396
@shanehebert396 Ай бұрын
The static padlock will restrict access and serialize *every* Example object, even though they are otherwise independent. You can make that a class member and it will then serialize for each object instance. You don't even need to allocate anything as each object has its own already... lock(this) { } will serialize access to that object (it's still a giant lock for everything that the object can do). You can make it even more fine grained by having a member variable specifically for Sum and locking it and having different padlocks for different members (if you had them).
@trexug6577
@trexug6577 Ай бұрын
I keep adding Nito.AsyncEx to my projects. It's a fine library, but I would love it if MS would make some more built-in functionality for async locks. I don't want to spend my threads waiting for locks, when they have better things to do.
@zglmorph
@zglmorph Ай бұрын
There should have been a dedicated Lock type starting back in .NET 1.0! As it is, every single heap-allocated object has extra overhead to be able to store locking information *just in case* someone might want to lock on that object, even though 99.9+% of objects will never be used as locks. AFAIK, the only reason they allowed everything to be usable in a lock statement is that they wanted to copy the Java idiom of "lock (this)". But Microsoft later came out with guidance saying not to use "lock (this)" because you don't want to lock on anything public, because if it's public then someone else could use it in their own lock statement, which could lead to deadlocks or data corruption. If they had come up with that guidance before .NET 1.0 was released, we might have had a Lock type in the very beginning.
@fusedqyou
@fusedqyou Ай бұрын
.NET has always been weird when it comes to thread safety. I'd say thread safety with these things still remains very weird, but at least they address these things with more reasonable solutions.
@shahzaibhassan2777
@shahzaibhassan2777 Ай бұрын
I saw Rust's multi threading much easier to make sense of
@victor1882
@victor1882 Ай бұрын
@@shahzaibhassan2777 until async comes into the picture
@keyser456
@keyser456 Ай бұрын
Mutex / locks have been adequate for most situations in my experience (been on since 1.0 beta, circa 2002). The ReaderWriterLock/Slim was a nice addition. What has been weird in your experience, specifically?
@Rick104547
@Rick104547 Ай бұрын
How is .NET weird with thread safety? If anything its pretty standard.
@mamicatatibe
@mamicatatibe Ай бұрын
<a href="#" class="seekto" data-time="413">6:53</a> Maybe I'm missing something, but shouldn't the IL code have the .EnterScope() functionality within the try-finally block as well so it makes sure the .Dispose() is called for the scope i.e. what if .EnterScope() blows up? (I haven't looked at what it does exactly, mind you)
@phizc
@phizc Ай бұрын
The try-finally block is to guarantee that the Monitor is exited if the was entered. Entering a try block can't fail, so the Monitor.Enter call can/should be outside it. The using statement works the same way in that the variable initialization is outside the try-finally block. E.g. using (var f = File.Open(fn)) { var b = f.ReadByte(); } becomes var f = File.Open(fn); try { var b = f.ReadByte(); } finally { f.Dispose(); }
@mamicatatibe
@mamicatatibe Ай бұрын
@@phizc thanks, for some reason I always thought it makes more sense for this to also be within the try block
@louisfrancisco2171
@louisfrancisco2171 Ай бұрын
@@mamicatatibe If the variable initialization is inside the try block, then the Dispose method could be called on an uninitialized variable.
@code8986
@code8986 11 күн бұрын
@@louisfrancisco2171The variable *declaration* needs to be outside of the try block, but couldn’t (and shouldn’t) the assignment (i.e. initialization) be *inside* the try block?
@louisfrancisco2171
@louisfrancisco2171 11 күн бұрын
@@code8986 If there were an exception between the start of the try block and the initialization, then the variable would be uninitialized. In the example above, if the file doesn't exist, execution would go to the finally block and you'd get a NullReferenceException from the call of Dispose on an unitialized variable.
@vbjay
@vbjay Ай бұрын
Just wanted to point out the fix of using interlocked to do the sum without locking. But the point was the locking.
@heischono4917
@heischono4917 25 күн бұрын
Why do I still have to manually create a variable in the code? A user-friendly implementation of "lock {...}" could create a variable of type Lock internally. What is the reason that I must declare the Lock variable?
@dimonasdf
@dimonasdf 24 күн бұрын
You can lock multiple access points to the same collection with the same lock object. Also, the object should already exist when the thread's code arrive at try enter, otherwise all threads would create their own objects, and nothing would be locked :)
@exemory
@exemory Ай бұрын
In this case with incrementing variable it's better to use Interlocked.CompareExchange method. This way you aren't blocking any threads and perform incrementing as an atomic operation
@phizc
@phizc Ай бұрын
How would that demonstrate the new Lock class?
@tarsala1995
@tarsala1995 Ай бұрын
`await` in `lock` is disallowed due to possible change of thread that is executing the code. Doubtful that MS will change that.
@diligencehumility6971
@diligencehumility6971 Ай бұрын
Would have been nice with a performance comparison
@mikol0158
@mikol0158 Ай бұрын
Why using lock when you have semaphore slim?
@jongeduard
@jongeduard Ай бұрын
I would appreciate it if Microsoft took a longer look at how Rust has solved the whole thing. It's a very different approach and possibly we will get that after they have introduced more next level code validation in general, but it would be a great development if they could take some ideas from it at least. Now there are still lots of ways to accidentally introduce race conditions in your code, there is nothing which actively helps you guarantee that you do things the right way.
@dusrdev
@dusrdev Ай бұрын
Is it supposed to replace only the simple lock on object, or types like the readerwriterlockslim as well?
@protox4
@protox4 Ай бұрын
The former.
@rikudouensof
@rikudouensof Ай бұрын
Have not used lock before
@code8986
@code8986 11 күн бұрын
You’ve been lucky :)
@rmcgraw7943
@rmcgraw7943 17 күн бұрын
SpinWait is your friend.
@adambickford8720
@adambickford8720 13 күн бұрын
Until it isnt
@pedrofpsimoes
@pedrofpsimoes Ай бұрын
I was happy for a while, but then it is the same hassle when using it with async-await LoL 😂
@mikewright2858
@mikewright2858 Ай бұрын
How is this better than the ReaderWriterLock?
@lordmetzgermeister
@lordmetzgermeister Ай бұрын
FYI you talk about new locks in C# 9 but it should be .NET 9
@eugene5096
@eugene5096 Ай бұрын
Not sure if this make a lot of difference if i would use Monitor explicitly
@protox4
@protox4 Ай бұрын
<a href="#" class="seekto" data-time="594">9:54</a> I wrote one!
@DaminGamerMC
@DaminGamerMC Ай бұрын
I dont really get why the sum isnt getting computed correctly. I have used parallel foreach to process large documents and never have gotten into an issue where they dont finish what they should. Could someone explain?
@vasiliychernov2123
@vasiliychernov2123 Ай бұрын
Adding an int is not an atomic operation. It first needs to read current value, then add an int and then write it back. Two threads can read the same value, add their ints and write it back, and so one write will be lost. So you need either to create a critical section with mutex (lock keyword) or use lock-free atomic operations, such as compare-and-swap which is a CPU instruction. Read current value and add an int, then use CAS which does this: if current value is equal to a passed value (we pass the one we read previously, i.e. it checks if the value has changed), write the new value. If CAS fails, we do everything again. Value equality check and writing the value happens atomically in this case.
@DaminGamerMC
@DaminGamerMC Ай бұрын
@@vasiliychernov2123 Thanks, put in that way makes a lot of sense.
@phizc
@phizc Ай бұрын
In short it's a race condition.
@jjxtra
@jjxtra 7 күн бұрын
Interlocked.*
@marvinalone
@marvinalone 24 күн бұрын
C#9 or .Net 9 ?
@code8986
@code8986 11 күн бұрын
You’re right, he should’ve said .NET 9.
@cocoscacao6102
@cocoscacao6102 Ай бұрын
Genuine question... What's the point of locking? It's just sequential code with extra steps...
@nickchapsas
@nickchapsas Ай бұрын
It’s about thread safety. Some operations might be 90% thread safe by default but they might have this 10% aspect of them that needs to be thread safe. You still gain 90% of performance by parallelizing most of it while locking what isn’t safe
@andersborum9267
@andersborum9267 Ай бұрын
It's basically to protect shared resources from race conditions, i.e. when two or more threads are competing for a limited resource (such as a shared integer, in Nick's example, which trivially could have been implemented using Interlocked.Increment).
@cocoscacao6102
@cocoscacao6102 Ай бұрын
@@nickchapsas Yeah but... have you ever encountered a situation where such code should exist? The best "real world" example that I can come up with is awaiting some multiple callbacks that eventually modify shared resource... But even then, I'd consider putting that operation in some queue or message broker... I never, ever used locks...
@sealsharp
@sealsharp Ай бұрын
​Queues made for concurrency hide the lock away from you.
@diadetediotedio6918
@diadetediotedio6918 Ай бұрын
@@cocoscacao6102 If you are implementing the queue processing you would use it.
@Tony-dp1rl
@Tony-dp1rl Ай бұрын
I can't think of a rational reason to lock an await call.
@Michael.SMarsh
@Michael.SMarsh Ай бұрын
Sounds like it'd be way simpler to just do FP and avoid mutating objects like the plague, and then learn and utilize whatever transactional and/or concurrency capabilities your persistence layer provides since that would then be the only place you'd have to coordinate state changes. edit: unless your doing something low-level/non "web-dev" in which case I'm completely outside of my wheelhouse
@mattfbk
@mattfbk Ай бұрын
ReaderWriterLockSlim
@cjrada82
@cjrada82 Ай бұрын
Why didn't they decide to support async code? - That's a disappointment
@GustavoHennig
@GustavoHennig Ай бұрын
The result is always different in kzbin.info/www/bejne/mGXWhpiYfbSHn5Y because you are not waiting for the Parallel.For to complete. This does not affect your point, but concurrency is not the cause of the value always being different. A more complex scenario would be required to demonstrate that.
@davilinkicefire
@davilinkicefire Ай бұрын
You partially right, he in fact doesn't check that the parallel.for is completed, but even if he waited for the run to complete, it would still result in having a different number at the end AND THE RESULT WILL STILL BE INCORRECT. The result at the end should equal to 1225 parallel.For doesn't not add thread-safety (or concurrency safety), is only that the 50 execution of the same code, and in the example, SHARE THE SAME REFERENCE of the class Example. You, as the developer, should ensure that the code that Parallel.For will execute is thread-safe (concurrency safe), Thread-safe mean that the code doesn't use share memory reference OR that they are protected against concurrency issue by issuing appropriate code synchronization mechanism (lock, semaphore, interlock, ...). he only use the parallel.for to quickly demonstrate a thread-safe issue that could be resolve by using a lock to demonstrate the new Lock type EDIT: remove the wrong end result
@JW-lv1fm
@JW-lv1fm Ай бұрын
@@davilinkicefire Factorial is multiplicative, hes doing additive. 1225 is 0 through 49 added.
@rauberhotzenplotz7722
@rauberhotzenplotz7722 Ай бұрын
Parallel.For is blocking
@davilinkicefire
@davilinkicefire Ай бұрын
@@JW-lv1fm You right, my bad
@GustavoHennig
@GustavoHennig Ай бұрын
@@rauberhotzenplotz7722 🤦‍♂You're right, it's blocking, I missed that.
@Eugene.Golubev
@Eugene.Golubev Ай бұрын
am I the only one, who've never used locking in my career as a web developer and always manage concurrency in DB?
@chralexNET
@chralexNET Ай бұрын
I think that is pretty normal for web developers, especially if you don't work on tooling or framework code. If what you do is just Create-Read-Update-Delete APIs and front-ends then you can pretty much just leave all that to the database as you said. Some examples of where I've used locking is for example to write rate limiters, for example when my backend needs to integrate with an external API. But it is also useful for example if you want to prevent a convoy of operations from e.g. hitting some external storage or cache service, to have a lock and for all requests to wait for the cache service to return a result, a lock can be used for that.
@fusedqyou
@fusedqyou Ай бұрын
This is a very common thing, especially when you want to efficiently handle multiple instances of the same work.
@Eugene.Golubev
@Eugene.Golubev Ай бұрын
@@chralexNET yeah, rate limiting is a good example I rarely write simple CRUDs. I usually write pretty complicated domain logic and optimistic concurrency solves most problems for me. I think, the more stateless your app is, the better
@diadetediotedio6918
@diadetediotedio6918 Ай бұрын
Well, the language is general purpose, it is not made specifically for you. I think it is alright for you to not require it, I myself almost never use locks nowadays for example (but I already used in the past for many things).
@devincarlson8866
@devincarlson8866 Ай бұрын
Even as a back end developer I hadn’t needed to use locks very frequently until recently. I had an API that ran background jobs to cache data into some singleton in-memory repositories from a DB for better performance since they were expensive queries. But I had a problem if an API query came in during the time that the cache was filling. I didn’t want to return an error, so I needed to await until the cache refill job had finished to read from the cache. So, I ended up using a SemaphoreSlim to do the job as Nick showed at the end here.
@amnesia3490
@amnesia3490 Ай бұрын
Would be nice if they address Task.Waits and UI Thread locking issues
@protox4
@protox4 Ай бұрын
That's not their problem, that's the programmer's problem. Don't use synchronous waits on asynchronous operations if you don't know what you're doing.
@Sergio_Loureiro
@Sergio_Loureiro Ай бұрын
~Nick Chapsas~ => *Nick Sharpsas*
@kvloover
@kvloover Ай бұрын
The lock syntax has always felt off and out of place in c#. Glad it's now a specific lock object, and I get that it's still using the same syntax for migrating, but I hope we get a more flowing syntax. The semaphore felt even worse the first usage, just because the term felt so out of place. It doesn't feel like the proper type to use just because it doesn't really state the usage.
@ManInTheFridge
@ManInTheFridge Ай бұрын
What's this like compared to Java? Is Java more elegant with their approach to using multithreading?
@adambickford8720
@adambickford8720 13 күн бұрын
Java has had explicit locks for many, many years. ReadOnly, ReadWrite, Reentrant, etc. It also has the intrinsic object monitors like C#. If you don't have async support, you'd better have decent locks. Modern java tends to use function paradigms like share nothing/immutable state
@clhoover4
@clhoover4 Ай бұрын
Don't use static, ever, all instances will have the same lock
@user-zz6fk8bc8u
@user-zz6fk8bc8u Ай бұрын
In this case it was definitely wrong, but "ever" isn't true either. There are quite a few situations where static lock objects are the only good solution.
@clhoover4
@clhoover4 Ай бұрын
@@user-zz6fk8bc8u The challenge from my experience is static variables creates a tight coupling, impacting testing, refactoring, evolution of the system, thread safety, etc...
@ilyahryapko
@ilyahryapko Ай бұрын
@@user-zz6fk8bc8u can you elaborate please?
@RiversJ
@RiversJ 15 күн бұрын
And if it's a shared system resource, instance level locks are worse than useless. The only Hard rule for anything with programming is quite simple = Use the right tool for the job You do not want to be a cargo cultist going with the first paradigm you learned for every problem.
@jonathansaindon788
@jonathansaindon788 Ай бұрын
Why not use Task.WhenAll?
@kelton5020
@kelton5020 Ай бұрын
Seems dumb. Why not just make a MonitorSlim class and update the compiler to use that instead for locking or something. Why do we need a Lock object, it seems like an unnecessary change.
@fusedqyou
@fusedqyou Ай бұрын
Here to say first before five others do.
@jessegador
@jessegador Ай бұрын
The Lock cannot be used in the async because it is a ref struct.
@phizc
@phizc Ай бұрын
You can't use async code inside a lock block with the old approach either.
@hellowill
@hellowill 11 күн бұрын
c# copying Java again after realising their way is wrong 🤣🤣🤣
@urbanelemental3308
@urbanelemental3308 Ай бұрын
The simple trick is to avoid locking whenever possible.
@user-kc8ey3py3y
@user-kc8ey3py3y Ай бұрын
Theres a lot of bad advice and incorrect statements in this video. Love your stuff usually Nick but this isnt up your usual standard
@nickchapsas
@nickchapsas Ай бұрын
Mind explaining?
@user-kc8ey3py3y
@user-kc8ey3py3y Ай бұрын
Sure. I think a lot of others have mentioned this too but having a static lock object is a bad idea. Yes here in this video it's fine kind of but there's no need and teaches people the incorrect approach. In general the lock object should be the same life time as the resources it is guarding access to. Here (and most often) it's protecting instance data and so the lock object should be an instance field. If it's static you end up locking across all instances which is not needed when you are protecting data specific to one instance. (Hope that makes sense. KZbin comments aren't the easiest place to voice this 😂). The other issue I spotted is the explanation of 'TryEnter' the timeout is not a limit to how long you can hold the lock. It's a limit for how long you'll wait to get it before it returns. Returning a Boolean indication of whether it successfully got the lock or not. Love you videos Nick and apologies if it came across rude. It's just I see a lot of these misconceptions around and you're usually a good source of correcting people
@dpduser
@dpduser Ай бұрын
I have seen that pattern for quite a long time. Using a static object means you are locking access to all objects, besides the one you are operating on. What you usually want (and no allocation is required) is to just call lock(this) { }.Only the target object is locked.
@JW-lv1fm
@JW-lv1fm Ай бұрын
lock(this) is bad standards, because this is public and anyone outside can unlock it. Another problem is that you don't indicate what logic you are locking. Sometimes when there are a lot of functions, its just nicer to say lock(SumVariableManipulationLock), in case you want to have more than 1 lock type for logic type, but now you partially indicate what its meant to keep threadsafe.
@dpduser
@dpduser Ай бұрын
@@JW-lv1fm Thanks for the comment. Regarding the "it is public" part, no, you cannot "unlock" it since (in this particular case) you could only invoke "Monitor.Exit()" from within the same thread that has acquired the lock. Regarding your second statemente, I absolutely agree with you: you may use "sub-locks" for more granular locking behaviour, but I would never make them static. In any case, my preference is going "lock-free" (when possible) via "interlocked" operations.
@louisfrancisco2171
@louisfrancisco2171 Ай бұрын
@@dpduser The problem is not that someone else can unlock it. It's that anybody can lock it.
@adambickford8720
@adambickford8720 13 күн бұрын
This was a known bad practice in java before C# stole it.
@joeldickson5471
@joeldickson5471 Ай бұрын
Locks themselves aren't performemt. Better to avoid them as much as possible imo, single threaded programing and queues really helps here. But still nicer syntax in c# 9 for when you need the lock
@Rick104547
@Rick104547 Ай бұрын
That really depends on what you are trying to achieve. I wouldn't say locks themselves are slow as they do their work in 10's of nanoseconds. They are used in alot of places even if you are not aware of them.
@JW-lv1fm
@JW-lv1fm Ай бұрын
That's not great advice. They exist for a reason. Anyone who's looking into locking already knows that something special is happening and needs to learn about them. This is actually a useful mechanism for high performance code (so calling them slow just means they've been used improperly - how do you single thread a queue lookup when you are waiting on an external resource, like a cold file? You would be blocking the other hot files with that queue). There are many types of locks as well, which could be made more mainstream/have better documentation I suppose: Spinlock, Mutex, Monitor, Semaphore, ReaderWriterLockSlim
@MatinDevs
@MatinDevs Ай бұрын
They should add GPU-Based compilation
@andr6087
@andr6087 Ай бұрын
Thank you for support Ukraine!
Stop Using IEnumerable The Wrong Way in .NET! | Code Cop #019
10:10
Method in java
25:35
Pawan Tutorial
Рет қаралды 8
黑天使遇到什么了?#short #angel #clown
00:34
Super Beauty team
Рет қаралды 45 МЛН
Lehanga 🤣 #comedy #funny
00:31
Micky Makeover
Рет қаралды 30 МЛН
Они так быстро убрались!
01:00
Аришнев
Рет қаралды 3,3 МЛН
ISSEI & yellow girl 💛
00:33
ISSEI / いっせい
Рет қаралды 22 МЛН
The Pattern You MUST Learn in .NET
20:48
Nick Chapsas
Рет қаралды 84 М.
.NET and C# are in trouble. Here is what I'd do.
10:57
Ed Andersen
Рет қаралды 34 М.
The New Option and Result Types of C#
15:05
Nick Chapsas
Рет қаралды 58 М.
The World Depends on 60-Year-Old Code No One Knows Anymore
9:30
Coding with Dee
Рет қаралды 749 М.
The Logging Everyone Should Be Using in .NET
15:34
Nick Chapsas
Рет қаралды 60 М.
I forced EVERYONE to use Linux
22:59
NetworkChuck
Рет қаралды 428 М.
Turns out REST APIs weren't the answer (and that's OK!)
10:38
Dylan Beattie
Рет қаралды 146 М.
Settling the Biggest Await Async Debate in .NET
14:47
Nick Chapsas
Рет қаралды 142 М.
Linus Torvalds: Speaks on Hype and the Future of AI
9:02
SavvyNik
Рет қаралды 171 М.
黑天使遇到什么了?#short #angel #clown
00:34
Super Beauty team
Рет қаралды 45 МЛН