4 ms·
> In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running actua
by novaleaf 10y ago
> In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running
actually, if you are into asynchronous programming (I am), I would claim the opposite. When writing an async program in C# you need to be acutely aware that in-between any two sequentially executed lines, entire threads of execution could have been invoked and completed. If you don't design for that, you WILL have race conditions.
Moving to nodejs 2 years ago, and something that I am still mindful of, is that you will NEVER have race conditions, as the entire user code will execute in a single thread, with interrupts only occurring between callbacks.
I like it because it's very easy to construct high performance professional apps in NodeJs (most devs are not multithreading experts) but sometimes I miss the idea of leveraging tons of cores. But that's why we scale horizontally (more 1 or 2 proc servers, less 32proc servers).
- MrDosu 10y agoI agree. Asynchronous programming is orders of magnitude easier to grasp than concurrency. Especially in low lock scenarios. Interlocked.Increment(yourPost) :P
- antihero 10y agoYou can still have race conditions anywhere IO is concerned, just not at a thread level (because no threads).
- simplify 10y agoThis is correct. Race conditions are still the most common vulnerability in web applications. Take a classic example: a one-time use coupon. Without some kind of locking, two simultaneous requests would be able to use the same coupon successfully. Roughly: 0.0s - [1] Client 1: Apply coupon 0.0s - [2] Client 2: Apply coupon 0.1s - [1] Server to database: Is coupon marked as used? 0.1s - [2] Server to database: Is coupon marked as used? 0.2s - [1] Database to server: Nope! All good. 0.2s - [2] Database to server: Nope! All good.* * Since the question was asked for both requests at the same time, the answer was "Not used" in both cases. 0.3s - [1] Server to database: Update coupon as used. 0.3s - [2] Server to database: Update coupon as used.* * Coupon has been used twice :( Node's async model is not going to help you here. You will need something more, such as a mutex.
- Chyzwar 10y agoNope, your ACID database will ensure that two writes in the same time for the same record will not happen. You don't even need to ask database if coupon is used. You just try to use coupon, if already used return message to user. Node give you freedom from Thread Hell. You enjoy similar performance without locks, threads, synchronisation. Race conditions happen but mostly with cache invalidation where you can have limited consistency guarantees.
- paulddraper 10y agoRight; you need to put your lock in the database, encoded as an index.
- simplify 10y agoThe problem isn't "two writes at the same time", it's the server thinking everything's OK for two separate users. If can model your database differently for this rudimentary example, then good for you – you're thinking about race conditions. Many web programmers do not think about them at all, and race conditions are usually not trivial to fix.
- Can_Not 10y ago> Use ACID compliant Database or not How is that specific to only NodeJs?
- novaleaf 10y agoagree. the coupon problem would be best fixed with atomic database transactions. in fact, an entirely synchronous, 1-user-at-a-time server wouldn't fix this, if there were two or more servers. and honestly, who would design any system that only supports 1 concurrent user?
- drewgross 10y agoCalling race conditions the "most common" vulnerability seems like some pretty extreme hyperbole. What about SQL injection or XSS?
- Klathmon 10y agoWhile it's not "true multithreading", there are a lot of options for using multiple cores in JS now. In the browser, there are web workers. When combined with the "transferrable" argument in the postMessage function [0] you can get zero-copy transfers (with the caveat that you can no longer access that variable from the process that sent it, so they are actually "transfers" not "copies" or "references"). They are not only here now, but they have pretty stellar browser support (back to IE10 and even safari 5.1). Node had it's own thing for a while as well, and there are many libraries on top of it to make it more capable or close to the web worker spec if you want. Sadly none of them seem to fully implement the web worker spec with the transferable objects ability, but there's no reason why that can't happen. Personally I prefer this method MUCH more than just giving you classic multithreading primitives and telling you to not shoot your eye out. Going along with what you said, it's significantly harder to get race conditions when you are either copying everything, or are actually transferring the data to someone else. It seems limiting at first, but I haven't hit anything personally that requires more than that to use 100% of the cores on a system. (the few times i've used it in production situations was setup to basically have the main thread split the data, then transfer them off to worker threads to be processed and either transferred back, or the result collected in the main thread when ready) That being said, there is some work happening on "SharedArrayBuffers" and Atomics [1] which are the real deal "you'll shoot your eye out" shared memory. And I believe they are well into the standardization process. Personally I'm going to avoid them like the plague, but I know that there are use cases out there that can't be solved with "transferrable objects". Mozilla has an MDN page on SharedArrayBuffer at [2] which is pretty useful. [0] https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage https://developer.mozilla.org/en-US/docs/Web/API/Worker/post... [1] http://tc39.github.io/ecmascript_sharedmem/shmem.html#AtomicsObject http://tc39.github.io/ecmascript_sharedmem/shmem.html#Atomic... [2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- friendzis 10y agoThe claim about line 2 executing right after line 1 breaks for any program running in concurrent context. Which is probably every nontrivial program dealing with side effects ever written, does not really matter whether that is C#, C++, JS or bare metal assembly. > something that I am still mindful of, is that you will NEVER have race conditions, as the entire user code will execute in a single thread If your runtime (kernel, VM, etc - not "user code") has theoretical possibility to change user memory/variable (call user code) concurrently, there is theoretical possibility to have race conditions. Concurrent runtime must have certain entry points to user code and everything that can be theoretically touched from these entry points must be treated dirty, which can get pretty expansive with complex callbacks. The only way to NEVER* have race conditions is to use polling - explicitly mark memory dirty (semantically in code) between "synchronisation points" having only flags/counters (in my view they are the same) for communication between userland and runtime. * If we allow for settling time and do not treat situations "read flag --> have flag value flipped --> execute based on old flag value" as race conditions.