How Thread Safety is Changing in .NET 9

  Рет қаралды 40,059

Nick Chapsas

Nick Chapsas

Күн бұрын

Пікірлер: 158
@user-zz6fk8bc8u
@user-zz6fk8bc8u 4 ай бұрын
The padlock at 2:50 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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
@@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 4 ай бұрын
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 3 ай бұрын
+1 for lock-free techniques
@jamesreynolds3167
@jamesreynolds3167 4 ай бұрын
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.
@LasseVågsætherKarlsen
@LasseVågsætherKarlsen 4 ай бұрын
7:45 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 4 ай бұрын
Could just be an implementation detail?
@MrWuffels
@MrWuffels 2 ай бұрын
@@billy65bob well this makes hell of a difference and a programmer using the lock should know that.
@urbanelemental3308
@urbanelemental3308 9 күн бұрын
Just updated my threading/sync libraries to support this: Open.Threading.ReadWrite and Open.Threading You are right about benchmarking, it's hard to see a difference.
@AL12rs
@AL12rs 4 ай бұрын
I'd love to hear more about best practices and libraries for Async locking
@mynameisshadywhat
@mynameisshadywhat 4 ай бұрын
Had to double check when this video was posted 4:45 you say C# 9 instead of .NET 9 😂
@modernkennnern
@modernkennnern 4 ай бұрын
There's some talk about `await lock` similar to `await foreach` to allow asynchronous locking
@hellowill
@hellowill 3 ай бұрын
locks belong to threads so async lock doesn't really make sense IMO. Should be a semaphore.
@anonymous49125
@anonymous49125 4 ай бұрын
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 3 ай бұрын
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 3 ай бұрын
​@@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.
@julianocs87
@julianocs87 4 ай бұрын
I had to check the date of the video when you mentioned C# 9 instead of .NET 9.
@vacantbill
@vacantbill 4 ай бұрын
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.
@silentdebugger
@silentdebugger 4 ай бұрын
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.
@leowong9885
@leowong9885 4 ай бұрын
Brings back memory of intro class to OS - mutex, p & v, monitor, critical session... Thanks for introducing the new lock mechanism.
@TheTim466
@TheTim466 4 ай бұрын
critical section*
@configadd
@configadd 4 ай бұрын
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 4 ай бұрын
not all methods are async, so locking with the Lock class may still be useful
@fusedqyou
@fusedqyou 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
Especially since if you enable true in the project file couldn't it just improve the code if it's the same?
@WileeRunner42
@WileeRunner42 4 ай бұрын
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 4 ай бұрын
isn't that just a semaphore?
@trexug6577
@trexug6577 4 ай бұрын
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.
@vbjay
@vbjay 4 ай бұрын
Just wanted to point out the fix of using interlocked to do the sum without locking. But the point was the locking.
@the-niker
@the-niker 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
​@@duffscsSemaphoreSlim works in Wasm
@GlebAOsokin
@GlebAOsokin 4 ай бұрын
I've read somewhere, that acquiring a SemaphoreSlim is ~10x slower than acquiring a simple lock...
@the-niker
@the-niker 4 ай бұрын
@@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 4 ай бұрын
@@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.
@Tesfamichael.G
@Tesfamichael.G 4 ай бұрын
Thanks for the update. I have a question though. Is the topic about .NET 9 or C#9. at 4:46, recorded audio: 'starting from c# 9 ... '. I guess you mean .NET 9
@diligencehumility6971
@diligencehumility6971 4 ай бұрын
Would have been nice with a performance comparison
@exemory
@exemory 4 ай бұрын
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 4 ай бұрын
How would that demonstrate the new Lock class?
@mamicatatibe
@mamicatatibe 4 ай бұрын
6:53 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 4 ай бұрын
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 4 ай бұрын
@@phizc thanks, for some reason I always thought it makes more sense for this to also be within the try block
@louisfrancisco2171
@louisfrancisco2171 4 ай бұрын
@@mamicatatibe If the variable initialization is inside the try block, then the Dispose method could be called on an uninitialized variable.
@code8986
@code8986 3 ай бұрын
@@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 3 ай бұрын
@@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.
@MayronWoW
@MayronWoW 4 ай бұрын
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 4 ай бұрын
The lock scope will be created for you on the boundaries of the lock if you lock a lock type
@chralexNET
@chralexNET 4 ай бұрын
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.
@georgepagotelis
@georgepagotelis 4 ай бұрын
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 4 ай бұрын
You could use an analyzer to create an error if lock is used with anything other than a Lock object.
@heischono4917
@heischono4917 3 ай бұрын
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 3 ай бұрын
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 :)
@rikudouensof
@rikudouensof 4 ай бұрын
Have not used lock before
@code8986
@code8986 3 ай бұрын
You’ve been lucky :)
@shanehebert396
@shanehebert396 4 ай бұрын
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).
@rmcgraw7943
@rmcgraw7943 3 ай бұрын
SpinWait is your friend.
@adambickford8720
@adambickford8720 3 ай бұрын
Until it isnt
@rmcgraw7943
@rmcgraw7943 2 ай бұрын
@@adambickford8720LOL, yeah, it sometimes makes you AwaitOnComplete, even UnsafeAwaitOnComplete
@dusrdev
@dusrdev 4 ай бұрын
Is it supposed to replace only the simple lock on object, or types like the readerwriterlockslim as well?
@protox4
@protox4 4 ай бұрын
The former.
@mikol0158
@mikol0158 4 ай бұрын
Why using lock when you have semaphore slim?
@tarsala1995
@tarsala1995 4 ай бұрын
`await` in `lock` is disallowed due to possible change of thread that is executing the code. Doubtful that MS will change that.
@fusedqyou
@fusedqyou 4 ай бұрын
.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 4 ай бұрын
I saw Rust's multi threading much easier to make sense of
@victor1882
@victor1882 4 ай бұрын
@@shahzaibhassan2777 until async comes into the picture
@keyser456
@keyser456 4 ай бұрын
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 4 ай бұрын
How is .NET weird with thread safety? If anything its pretty standard.
@_grigoryta
@_grigoryta 4 ай бұрын
1:09 Paralyzed loop? Didn't know programming concepts could have disabilities. What a diverse world we live in
@artemisDev
@artemisDev 4 ай бұрын
When there's a deadlock in your parallelized loop.
@foxgodess9
@foxgodess9 4 ай бұрын
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
@zglmorph
@zglmorph 4 ай бұрын
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.
@mikewright2858
@mikewright2858 4 ай бұрын
How is this better than the ReaderWriterLock?
@jongeduard
@jongeduard 4 ай бұрын
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.
@DaminGamerMC
@DaminGamerMC 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@vasiliychernov2123 Thanks, put in that way makes a lot of sense.
@phizc
@phizc 4 ай бұрын
In short it's a race condition.
@protox4
@protox4 4 ай бұрын
9:54 I wrote one!
@lordmetzgermeister
@lordmetzgermeister 4 ай бұрын
FYI you talk about new locks in C# 9 but it should be .NET 9
@eugene5096
@eugene5096 4 ай бұрын
Not sure if this make a lot of difference if i would use Monitor explicitly
@pedrofpsimoes
@pedrofpsimoes 4 ай бұрын
I was happy for a while, but then it is the same hassle when using it with async-await LoL 😂
@YukonianOrangutangInSpace
@YukonianOrangutangInSpace 4 ай бұрын
Very informative, thank you! Excited for this.
@mattfbk
@mattfbk 4 ай бұрын
ReaderWriterLockSlim
@Tony-dp1rl
@Tony-dp1rl 4 ай бұрын
I can't think of a rational reason to lock an await call.
@marvinalone
@marvinalone 3 ай бұрын
C#9 or .Net 9 ?
@code8986
@code8986 3 ай бұрын
You’re right, he should’ve said .NET 9.
@Michael.SMarsh
@Michael.SMarsh 4 ай бұрын
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
@jjxtra
@jjxtra 3 ай бұрын
Interlocked.*
@kvloover
@kvloover 4 ай бұрын
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.
@amnesia3490
@amnesia3490 4 ай бұрын
Would be nice if they address Task.Waits and UI Thread locking issues
@protox4
@protox4 4 ай бұрын
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.
@cj82-h1y
@cj82-h1y 4 ай бұрын
Why didn't they decide to support async code? - That's a disappointment
@cocoscacao6102
@cocoscacao6102 4 ай бұрын
Genuine question... What's the point of locking? It's just sequential code with extra steps...
@nickchapsas
@nickchapsas 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
​Queues made for concurrency hide the lock away from you.
@diadetediotedio6918
@diadetediotedio6918 4 ай бұрын
@@cocoscacao6102 If you are implementing the queue processing you would use it.
@jessegador
@jessegador 4 ай бұрын
The Lock cannot be used in the async because it is a ref struct.
@phizc
@phizc 4 ай бұрын
You can't use async code inside a lock block with the old approach either.
@ManInTheFridge
@ManInTheFridge 4 ай бұрын
What's this like compared to Java? Is Java more elegant with their approach to using multithreading?
@adambickford8720
@adambickford8720 3 ай бұрын
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
@Sergio_Loureiro
@Sergio_Loureiro 4 ай бұрын
~Nick Chapsas~ => *Nick Sharpsas*
@Eugene.Golubev
@Eugene.Golubev 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
This is a very common thing, especially when you want to efficiently handle multiple instances of the same work.
@Eugene.Golubev
@Eugene.Golubev 4 ай бұрын
@@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 4 ай бұрын
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 4 ай бұрын
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.
@jonathansaindon788
@jonathansaindon788 4 ай бұрын
Why not use Task.WhenAll?
@clhoover4
@clhoover4 4 ай бұрын
Don't use static, ever, all instances will have the same lock
@user-zz6fk8bc8u
@user-zz6fk8bc8u 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
@@user-zz6fk8bc8u can you elaborate please?
@RiversJ
@RiversJ 3 ай бұрын
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.
@GustavoHennig
@GustavoHennig 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@davilinkicefire Factorial is multiplicative, hes doing additive. 1225 is 0 through 49 added.
@rauberhotzenplotz7722
@rauberhotzenplotz7722 4 ай бұрын
Parallel.For is blocking
@davilinkicefire
@davilinkicefire 4 ай бұрын
@@JW-lv1fm You right, my bad
@GustavoHennig
@GustavoHennig 4 ай бұрын
@@rauberhotzenplotz7722 🤦‍♂You're right, it's blocking, I missed that.
@fusedqyou
@fusedqyou 4 ай бұрын
Here to say first before five others do.
@kelton5020
@kelton5020 4 ай бұрын
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.
@urbanelemental3308
@urbanelemental3308 4 ай бұрын
The simple trick is to avoid locking whenever possible.
@dpduser
@dpduser 4 ай бұрын
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 4 ай бұрын
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 4 ай бұрын
@@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 4 ай бұрын
@@dpduser The problem is not that someone else can unlock it. It's that anybody can lock it.
@adambickford8720
@adambickford8720 3 ай бұрын
This was a known bad practice in java before C# stole it.
@DaveQuinn-k6x
@DaveQuinn-k6x 4 ай бұрын
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 4 ай бұрын
Mind explaining?
@DaveQuinn-k6x
@DaveQuinn-k6x 4 ай бұрын
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
@hellowill
@hellowill 3 ай бұрын
c# copying Java again after realising their way is wrong 🤣🤣🤣
@MatinDevs
@MatinDevs 4 ай бұрын
They should add GPU-Based compilation
@andr6087
@andr6087 4 ай бұрын
Thank you for support Ukraine!
LINQ's INSANE Improvements in .NET 9
11:26
Nick Chapsas
Рет қаралды 60 М.
What's New in .NET 9 with Examples
25:02
Nick Chapsas
Рет қаралды 46 М.
СКОЛЬКО ПАЛЬЦЕВ ТУТ?
00:16
Masomka
Рет қаралды 3,4 МЛН
Why no RONALDO?! 🤔⚽️
00:28
Celine Dept
Рет қаралды 61 МЛН
Settling the Biggest Await Async Debate in .NET
14:47
Nick Chapsas
Рет қаралды 147 М.
The New Option and Result Types of C#
15:05
Nick Chapsas
Рет қаралды 79 М.
Stop Using FirstOrDefault in .NET! | Code Cop #021
12:54
Nick Chapsas
Рет қаралды 94 М.
Is Functional Programming DEAD Already?
21:07
Continuous Delivery
Рет қаралды 68 М.
How is this Website so fast!?
13:39
Wes Bos
Рет қаралды 1 МЛН
What is Span in C# and why you should be using it
15:15
Nick Chapsas
Рет қаралды 260 М.
.NET and C# are in trouble. Here is what I'd do.
10:57
Ed Andersen
Рет қаралды 104 М.
How Senior Programmers ACTUALLY Write Code
13:37
Thriving Technologist
Рет қаралды 1,6 МЛН
"Stop Using Async Await in .NET to Save Threads" | Code Cop #018
14:05