diff --git a/pkgs/racket-doc/scribblings/reference/eval-model.scrbl b/pkgs/racket-doc/scribblings/reference/eval-model.scrbl index 0928ce6949..32a9e4a5e4 100644 --- a/pkgs/racket-doc/scribblings/reference/eval-model.scrbl +++ b/pkgs/racket-doc/scribblings/reference/eval-model.scrbl @@ -953,18 +953,42 @@ Racket supports multiple @deftech{threads} of evaluation. Threads run concurrently, in the sense that one thread can preempt another without its cooperation, but threads currently all run on the same processor (i.e., the same underlying operating system process and thread). See also -@secref["futures"]. +@secref["futures"] and @secref["places"]. Threads are created explicitly by functions such as @racket[thread]. In terms of the evaluation model, each step in evaluation actually deals with multiple concurrent expressions, up to one per thread, rather than a single expression. The expressions all share the same objects and top-level variables, so that they can -communicate through shared state, and sequential consistency is +communicate through shared state, and @defterm{sequential consistency} @cite["Lamport79"] is guaranteed (i.e., the result is consistent with some global sequence imposed on all evaluation steps across threads). Most evaluation steps involve a -single step in a single expression, but certain synchronization -primitives require multiple threads to progress together in one step. +single step in a single thread, but certain synchronization +primitives require multiple threads to progress together in one step; for example, +an exchange of a value through a @tech{channel} progresses in two +threads simultaneously. + +Unless otherwise noted, all constant-time procedures and operations +provided by Racket are thread-safe in the sense that they are +@defterm{atomic}: they happen as a single evaluation step. +For example, @racket[set!] assigns to a variable as an atomic action +with respect to all threads, so that no thread can see a +``half-assigned'' variable. Similarly, @racket[vector-set!] assigns to +a vector atomically. Note that the evaluation of a @racket[set!] +expression with its subexpression is not necessarily atomic, because +evaluating the subexpression involves a separate step of evaluation. +Only the assignment action itself (which takes after the subexpression +is evaluated to obtain a value) is atomic. Similarly, a procedure +application can involve multiple steps that are not atomic, even if +the procedure itself performs an atomic action. + +The @racket[hash-set!] procedure is not atomic, but the table is +protected by a lock; see @secref["hashtables"] for more information. +Port operations are generally not atomic, but they are thread-safe in +the sense that a byte consumed by one thread from an input port will +not be returned also to another thread, and procedures like +@racket[port-commit-peeked] and @racket[write-bytes-avail] offer +specific concurrency guarantees. In addition to the state that is shared among all threads, each thread has its own private state that is accessed through @deftech{thread diff --git a/pkgs/racket-doc/scribblings/reference/reference.scrbl b/pkgs/racket-doc/scribblings/reference/reference.scrbl index 52bb68ab3a..476df10720 100644 --- a/pkgs/racket-doc/scribblings/reference/reference.scrbl +++ b/pkgs/racket-doc/scribblings/reference/reference.scrbl @@ -168,7 +168,13 @@ The @racketmodname[racket] library combines #:location "Principles and Practice of Parallel Programming" #:date "1990") - (bib-entry #:key "L'Ecuyer02" + (bib-entry #:key "Lamport79" + #:title "How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs" + #:author "Leslie Lamport" + #:location "IEEE Transactions on Computers" + #:date "179") + + (bib-entry #:key "L'Ecuyer02" #:author "Pierre L'Ecuyer, Richard Simard, E. Jack Chen, and W. David Kelton" #:title "An Object-Oriented Random-Number Package With Many Long Streams and Substreams" #:location "Operations Research, 50(6)" diff --git a/pkgs/racket-doc/scribblings/reference/threads.scrbl b/pkgs/racket-doc/scribblings/reference/threads.scrbl index e8b5526673..21e8b48621 100644 --- a/pkgs/racket-doc/scribblings/reference/threads.scrbl +++ b/pkgs/racket-doc/scribblings/reference/threads.scrbl @@ -6,7 +6,7 @@ @guideintro["concurrency"]{threads} See @secref["thread-model"] for basic information on the Racket -thread model. See also @secref["futures"]. +thread model. See also @secref["futures"] and @secref["places"]. When a thread is created, it is placed into the management of the @tech{current custodian} and added to the current @tech{thread @@ -31,19 +31,6 @@ A thread can be used as a @tech{synchronizable event} (see @secref["sync"]). A thread is @tech{ready for synchronization} when @racket[thread-wait] would not block; @resultItself{thread}. -All constant-time procedures and operations provided by Racket are -thread-safe because they are @defterm{atomic}. For example, -@racket[set!] assigns to a variable as an atomic action with respect -to all threads, so that no thread can see a ``half-assigned'' -variable. Similarly, @racket[vector-set!] assigns to a vector -atomically. The @racket[hash-set!] procedure is not atomic, but -the table is protected by a lock; see @secref["hashtables"] for more -information. Port operations are generally not atomic, but they are -thread-safe in the sense that a byte consumed by one thread from an -input port will not be returned also to another thread, and procedures -like @racket[port-commit-peeked] and @racket[write-bytes-avail] offer -specific concurrency guarantees. - @;------------------------------------------------------------------------ @section{Creating Threads}