language is one in which two activations of a method simply cannot
run simultaneously within the same object. All methods are locked on an object automatically
and by default
That definition is incorrect, especially in its focus on locks. Try this:
language is one in which the program is guaranteed to compute the same result regardless of whether it it is run with one thread or many. Concurrent threads are automatically protected from contention, such that there is no danger of DeadLock
guarantees this. Languages with other mechanisms such as automatic locking, automatic mutual exclusion, snapshot/rollback, lock free shared data structures, etc. are often misleadingly called
- I don't think either Erlang or any other languages has ReferentialTransparency, once it starts to ping-pong messages across process boundaries to have a distributed/parallel system. It's I/O and they're not even pure any more.
See also MultiCpuConcurrency?
Lock free data structures have been the subject of a great deal of research in recent years, see for instance http://www.cl.cam.ac.uk/Research/SRG/netos/lock-free/
Thread Safe Languages
- This should probably be called "automatic dead-locking"
- Pure FunctionalProgrammingLanguages are ThreadSafe.
- ErlangLanguage, by avoiding shared state between tasks (each task has its own state and tasks, or processes in Erlang, communicate by messages) avoid many synchronization issues (such as race conditions due to concurrent access to an object). But not all; deadlock and other phenomena that cause a task to fail to make progress are still possible (two processes can achieve deadlock by waiting for the other to communicate with them). See CommunicatingSequentialProcesses.
Warning: the above operates with a loose and mostly useless definition of thread safety.
This is a fundamentally wrong idea, and we should be knowing this ever since the 60's. The phenomena of nature is essentially non-deterministic, parallel and councurrent. What we need is programming languages, formal methods, programmer education, etc, that deal with non-determinism as essential part of computing and not merely as an annoyance or something we have to be isolated from. This is what EwDijkstra
has advocated for decades.
The rest of the things below is garbage. ErlangLanguage
isn't inherently more safe for writing parallel programs than say, Java. Erlang programs as any other distributed programs may suffer from deadlock while running parallel/distributed/concurrent computations just as Java programs do. Likewise they may suffer from starvation, interference, incorrect results, etc. There's no programming language level abstraction that will isolate the programmer from having to reason
on non-deterministic computations. What it is safe to say about Erlang is that message passing paradigm as in Erlang may make the reasoning about concurrent programs easier than Java's paradigm based on locks and side-effects, but not essentially easier.
The undesirable phenomena of concurrent computations, namely deadlock, starvation, interference, incorrectness, etc (as well as the difficulty of achieveing the desirabile properties safety/progress/correctness), are essential
to any concurrent computations, the theory of distributed/concurrent/parallel programs has been developped abstracted away from any particular language paradigm. The quest for ThreadSafeLanguage
can thus be assimilated with the quest for a Turing-complete language in which the HaltingProblem
is decidable. --CostinCozianu
I follow the line of thought, but has this actually been proven mathematically? Because if not (and I hadn't heard of such a result), then the quest for a ThreadSafeLanguage
seems like a worthy one.
- Deadlocking is halting, the rest follows. -- dm, not C.C.
[How is that, exactly? Look at the definition of "thread safe" above. Do you really want a "thread safe" language, where two threads cannot operate on the same object at once? Of course not. Under any characterization of "object", you want multiple threads to be able to operate on the same object at once in many circumstances. Otherwise, the degree of parallelism you have will be absolutely minimal and there would be no point to threads at all. What you do not want to have is two threads operating on the same object at once in certain kinds of ways, ways that end up damaging or corrupting the object. But what these ways are is not clear ahead of time. Indeed, what objects are is not clear ahead of time. In the dining philosophers problem, each fork may seem to be an object. Naturally speaking, it is forks that are objects after all. But in solving the problem we require to consider the collection of forks to be an object which must be dealt with in special ways. I don't see how "automatically locking" each individual fork isn't going to get us anywhere. ]
Languages with ReferentialTransparency
(e.g. functional languages) have no concept of threading whatsoever: because they have no concept of a thread of control they can have no concept of multiple
threads of control. Whether or not the language runtime uses multiple threads or CPUs to evaluate subexpressions in parallel is completely hidden from the programmer; the programmer has no control over concurrency.
That is, with ReferentialTransparency
, each function always returns the same result for a given set of parameter values; there are no writes that could step on each other.
While Costin is correct in that proving an arbitrary concurrent system to be deadlock-free is undecideable, the quest for a ThreadSafeLanguage
(or better, a thread-safer
language) isn't worthless. At a minimum, modern languages should provide mechanisms to limit/prevent/discourage simple and blatant synchronization errors. Writing a (correct) concurrent program in Java or Erlang is easier than writing one in C.
That's got to be worth something.
Costin is also correct (IMHO) in that the real world is frequently non-deterministic; and too many computer programs and computer systems require being able to atomically query or modify the "state of the whole world". Such systems are inherently unscaleable; the reason should be obvious. For a mental exercise, imagine what would happen if the CEO of Bank of America went to his CIO and demanded to know the exact sum value of all
accounts managed by BofA at a particular moment in time? Such a thing could be computed--simply freeze all banking activity worldwide, tabluate the sum, then allow normal activity to continue. However, the means to do so are prohibitively expensive and flat-out unacceptable to BofA and its customers. So the CEO doesn't ask such a thing; or instead asks for an approximation which is tractable to compute.
[If the moment in time is sufficiently in the past; and the bank's transactions are recorded in a log, then the computation becomes non-disruptive provided that all necessary log entries are posted and available. OTOH, "what is the total now?" still is a problem.]
There are many other such examples of things which are DisruptiveToCompute?
, that shouldn't be computed--and aren't in the real world.
Programming in a ThreadSafeLanguage
won't fix any of this, BTW.