I have a hypothesis that being dynamic has no particular effect on the complexity of multithreading. I think the apparent effect is a combination of two things: 1. All our dynamic scripting languages in modern use date from the 1990s before this degree of threading was a concern for the languages and 2. It is really hard to retrofit code written for not being threaded to work in a threaded context, and the "deeper" the code in the system the harder it is. Something like CPython is about as "deep" as you can go, so it's really, really hard.
I think if someone set out to write a new dynamic scripting language today, from scratch, that multithreading it would not pose any particular challenge. Beyond that fact that it's naturally a difficult problem, I mean, but nothing special compared to the many other languages that have implemented threading. It's all about all that code from before the threading era that's the problem, not the threading itself. And Python has a loooot of that code.
Does it? The GIL only ensured each interpreter instruction is atomic. But any group of instruction is not protected. This makes it very hard to rely on the GIL for synchronization unless you really know what you are doing.
If I understand that correctly, it would mean that running a function like this on two threads f(1) and f(2) would produce a list of 1 and 2 without interleaving.
def f(x):
for _ in range(N):
l.append(x)
I've tried it out and they start interleaving when N is set to 1000000.
Dynamic(ally typed) languages, by virtue of not requiring strict typing, often lead to more complicated function signatures.
Such functions are generally harder to reason about. Because they tend to require inspection of the function to see what is really going on.
Multithreaded code is incredibly hard to reason about. And reasoning about it becomes a lot easier if you have certain guarantees (e.g. this argument / return value always has this type, so I can always do this to it). Code written in dynamic languages will more often lack such guarantees, because of the complicated signatures. This makes it even harder to reason about Multithreaded code, increasing the risk posed by multithreaded code.
When the language is dynamic there is less rigor. Statically checked code is more likely to be correct. When you add threads to "fast and loose" code things get really bad.
Unless your claim is that the same error can happen more times per minute because threading can execute more code in the same timespan, this makes no sense.
Some statically checked languages and tools can catch potential data races at compile time. Example: Rust's ownership and borrowing system enforces thread safety at compile time. Statically typed functional languages like Haskell or OCaml encourage immutability, which reduces shared mutable state — a common source of concurrency bugs. Statically typed code can enforce usage of thread-safe constructs via types (e.g., Sync/Send in Rust or ConcurrentHashMap in Java).
I installed ubuntu for my mother, she just needs to download pdfs and read pdfs, look at images, use gmail. Sometimes she opens a document with LibreOffice, but no power usage.
Seems to work, the maintenance is also now super easy, ssh, update. Something wrong and she needs support? I ssh, open up a tunnel and connect via remina to her desktop to explain.
I had a situation once when Ubuntu did literally not go into the Desktop Environment anymore, but all I did was update and upgrade packages and it started working again.
This is normal in business. Now that tech dominates they use that market position to setup monopolies. If we had functional anti-trust laws then it wouldn't feel so dire. Allowing monopolies in a capitalist system is the worst economic policy since socialism.
I remember being grilled for not creating "jsony" interfaces:
message Response {
string id = 1;
oneof sub {
SubTypeOne sub_type_one = 2;
SubTypeTwo sub_type_two = 3;
}
}
message SubTypeOne {
string field = 1;
}
message SubTypeTwo {
}
In your current model you just don't have any fields in this subtype, but the response looked like this with our auto translator:
{ "id": "id", "sub_type_two": { } }
Functionally, it works, and code written for this will work if new fields appear. However, returning empty objects to signify the type of response is strange in the web world. But when you write the protobuf you might not notice
reply