5 ms·
> [Go] failed to provide a safe concurrency model. What did he mean by this?
by kebolio 10y ago
> [Go] failed to provide a safe concurrency model.
What did he mean by this?
- nothrabannosir 10y agoGo doesn't protect you against race conditions, it merely offers some concurrency tools. There is nothing to declare ownership of objects in memory. So the compiler doesn't (can't) complain if you share memory and access it simultaneously. At best, there are runtime checks. Rust does offer compiler protection against that. Edit: "merely", relatively to Rust :) on an absolute scale, still way better than C for concurrency.
- VexorLoophole 10y agoAs a total beginner (learning programming by myself since 2 or 3 years), i am always asking myself, how often "little" things like race conditions break something in production. Sure thing, some applications need to be safe-super-safe. But is it worth to switch over from go to rust as a beginner, since go is the unsafer language? I know, that there is no ultimate language. But i always asked myself i am missing a point, since i never really had problems like that occur. I also wrote something little in clojure (wanted to write something in lisp, and clojure presented itself somehow modern). But many people told me about how bad clojure is, because it is not type-safe. So i switched to go. And i have to say, it is really nice, to be forced to use the right types as input. But will i have the same experience when i switch over to rust and think to myself: "Whoa yes, i never though about that aspect, but it really helps me as a beginner who tends to write slobby programms!"?
- Cyph0n 10y agoIt becomes a problem when you're building applications with complex interactions, and is even worse with large codebases that are tough to debug and reason about.
- camus2 10y ago> i am always asking myself, how often "little" things like race conditions break something in production It can basically corrupt the whole program. I bet half go apps out there have data race. People who boast about Go's simplicity can't even see the elephant in the room. A simplistic type system doesn't fix unsafe concurrency. You'd think that safe concurrency would be an important design goal for a highly concurrent language, well apparently it isn't.
- fortytw2 10y agoIn fairness, Go has an extremely good race detector (run/test with -race to enabled it), and makes no guarantees about memory or correctness if you write code with races in it
- llogiq 10y agoLast time I checked, the race detector could only find a certain percentage of data races – those easier to detect . The crux with such systems is you tend to rely on them...
- moomin 10y agoSpeaking as an experienced programmer: all the time, in subtle ways, sometimes that you don't notice for a long time. Sometime benign, sometimes your data has been being corrupted for months before you notice. My standard advice on concurrency is, quite simply, don't. It always looks way simpler than it actually is. If you're doing something that _requires_ it, get all the help you can. Type-level enforcement sounds _excellent_ to me.
- macintux 10y agoIf you want to avoid data corruption in concurrent software, there's always Erlang as an option.
- pimeys 10y agoI haven't checked Erlang too well, but is it so that the concurrency in Erlang software is basically actors only? Of course in this space you can also use Akka and even Rust and C++ have actor libraries available. But there are definitely use cases where you don't want to use actors, where you might want to compose several futures together without the overhead of actor mailboxes.
- marcosdumay 10y ago> how often "little" things like race conditions break something in production Often. Way too often. And it always break at 3 in the morning when you are hiking somewhere where there is no internet connection. Besides, race conditions tend to break on the worst possible ways. It either silently corrupts data, or makes your system stop working but stay active, so the OS does not know it must launch a new instance.
- staticassertion 10y agoData races definitely happen in the real world and they are awful to track down, because they only happen n% of the time. All of my least favorite bug-fix experiences have been data races.
- hackermailman 10y agoYou can also check out some CMU public calendars and read their lecture notes about safe standards in programming or get introduced to contracts just so you get better at eyeballing your own libraries to look for obvious errors https://www.cs.cmu.edu/~rjsimmon/15122-s16/schedule.html https://www.cs.cmu.edu/~rjsimmon/15122-s16/schedule.html They also have distributed programming course lecture notes that are open to the public with golang specific info on how to deal with race conditions. You'll have the same experience in Rust if you research why they've done certain things, but can quickly get lost on the mailing list unless you've read books like EoPL http://www.eopl3.com/ http://www.eopl3.com/
- nickpsecurity 10y agoThink about effort in vs results gained. Example: You can drive nails with a knife by holding the nail and hitting it with the side of the knife. It takes work to do right with you occasionally cutting yourself. Some people will even loose a hand. You can use a hammer. You will get the nails in smoother with less rework required. You occasionally hurt yourself but not as bad as a knife. You can also smash the nerves to point you don't feel anything. You can use a nailgun with safety switch. It's ultra-fast and can't hurt you if you're aiming where the nails go. It cost a bit more. It can hurt you if you turn the safety off or aim it at yourself. Simpler than mental effort into using knives or hammers safety. Less tiring, too. Some people even think they're fun. That's C, C++, and languages that are memory-safe respectively. Rust's advantage of no GC is like a nail-gun that costs same as a hammer. It has the benefits but not the primary disadvantage. If you're a craftsman, you're time and energy are valuable. Use the best tools you can for whatever work you're doing. That is, what gets it done quickly, done right, and easy to fix later w/ smaller problems.
- stymaar 10y agoI don't know why you are downvoted since your question is legit. I'll answer given my own experience : At my former company, we had a websocket-based service that allowed symetric communication between the clients. We had around 10% connection failures, and we thought it was causes by websocket well-known incompatibilities with some network stack, and we had a fallback to ajax polling. Several month later, someone touched this part of the code and found a data race. After we fixed it, the failure rate dropped to 5%. Is 5% of failure big ? It depends on your business. In our case it wasn't too bad because we had a backup plan. But if every customer have a 5% chance of application breakage each time he connects, you may have trouble building a big user-base.
- kbenson 10y agoThese are some of the bugs I hate the worst. When you have a plausible explanation about why it's slow, or fails sometimes, and it isn't under your control (or is way out of your purview), it's far to easy to stop lookingand not find your own bugs that exacerbate the problem. Because if you don't have a bug, and it is all that external problem, you just wasted all that time looking. Finding that bug later is especially painful, as you realize a little more time initially may have saved so many problems later. :/
- djsumdog 10y agoI've had to deal with several race conditions. They're easy to miss and difficult to debug once you have a system that starts scaling up to millions of transactions per day.
- dispose13432 10y ago>As a total beginner (learning programming by myself since 2 or 3 years), i am always asking myself, how often "little" things like race conditions break something in production Rookie mistake (and a shoot-yourself-in-the-foot-at-2-am) mistake coming up: package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { fmt.Printf("i= %d\n", i) wg.Done() }() } wg.Wait() } https://play.golang.org/p/XDzFq_XK_1 https://play.golang.org/p/XDzFq_XK_1 And what about this code: package main import "fmt" func main() { var intArray []int for i := 0; i < 1000; i++ { intArray = append(intArray, i) fmt.Printf("i= %d\n", i) } fmt.Println(intArray) } https://play.golang.org/p/UuI4uESZ_f https://play.golang.org/p/UuI4uESZ_f If you don't care if intArray is in the proper order, you might do something like this: package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup var intArray []int for i := 0; i < 1000; i++ { wg.Add(1) go func(i int) { intArray = append(intArray, i) fmt.Printf("i= %d\n", i) wg.Done() }(i) } wg.Wait() fmt.Println(intArray) } What's wrong? On my multi-core computer (though not on playground), len(intArray) could be as low as 500! Why? Because a = append isn't atomic. Go, which is so pedantic about "stupid" mistakes (including something, changing your mind, and not "unincluding" it), didn't catch this. Not an error and no warning. But the worst part is that when you loop until 10, it works. You can unit test it, integrate test it, and have it break at any point in time.
- ctz 10y agoGo has data races, which can break memory safety in some limited cases: https://research.swtch.com/gorace https://research.swtch.com/gorace