At 08:27 PM 3/30/2002 +0100, ducasse wrote:
I do not have the expertise but I would like to know how we could improve the thread model of Squeak. I started to look at Mozart which apparently has a good thread model and was wondering if it could be possible to imporve the one of Squeak.
Have you any intention in this direction? Squeak belongs also to the people that improve it ;)
My one reservation is the threads. ...
There's several ways to have good support for threads:
1) no stupid restrictions on how many.
2) locks should be fast -- ideally, about as fast as a bus-locked compare-and-swap (or load-linked/store-conditional) to acquire or release one. They should also be pretty near fair (FIFO) in how they give competing threads access to the lock. Note that this is independent of how "lock" is spelled in the source language -- when you rip away the abstractions, there's mutual exclusion at the bottom, and threads are competing for access, and it should be fast and fair.
3) there should probably be a useful set of different lock types provided. Not only do people botch them when they roll their own, the underlying implementation can probably do them faster. Java's a little sparse here -- you get synchronized, wait, notify, that's all. (Modula-3 is the same.) You might find yourself wanting (e.g.) reader/writer locks, so that you could have many concurrent readers.
4) there needs to be a consistent/complete set of primitives. Java and Modula-3 do okay here -- you can use sync/wait/notify to build all the others without gratuitous busy-waiting etc. It's not a comprehensive set of operations, but it is at least consistent and complete.
5) don't do what Java did -- don't make "any object" also able to function as a lock. It's painful to implement, steals bits from your garbage collector, and (in a big system, or one that you want to be secure) not useful anyway.
6) wouldn't hurt a bit to go look at Doug Lea's work with Java. I regard most of what he did as "Java needed this, but they left it out, so here is something that does what you need and works".
The answer I just gave you is conventional and low-risk. Periodically people come up with "you really ought to do it this way" formulations for locking, but most of these never seem to catch on. I don't know if it's because of insufficient bandwagon, or if they are fundamentally flawed, or if (it turns out that) ubiquitous locking is just too damn expensive (it IS quite expensive on many multiprocessors). There is also Erlang, which I don't know enough about.
One reservation I have about locking, concurrency, and OO in general, is whether there's a plain old conflict in the styles. There's problems in some of the Java libraries, with objects that can "change". They inherited too much from C/C++, and many of the data structures are mutable by default. That forces synchronization on both modify and on access, and (because Java synchronization is simple exclusive access) that creates inefficiencies and bottlenecks. Worst thing is, in a big system you cannot "take advantage" (as if it were a good thing) of this mutability, because the objects are shared, and you don't know whether the other viewers are prepared for the change.
It is "better", both in avoiding needless sync cost, and because you don't really know who is referencing what, to adopt an idiom where (shared) objects are initialized, and never change state after that. Not completely functional, but more nearly functional. This isn't true for all objects, but in general, there's lots of them that should not be gratuitously mutable. How will this fit with Squeak?
There is a high-risk answer, also, that is independent of how you present threads/locking to users. If you want high performance, you'll either need to restrict your attention to the (empty?) set of OSes with good thread support, or else you'll have to do it yourself, at the very lowest level. We lean heavily on the compiler in the Java system that I worked on (30,000 threads possible) and also use unorthodox calling conventions that have to be hidden from native code. In an interpreted system, it's not quite so extreme, but you still have to be careful with your I/O libraries.
David Chase