Threads |
Separate threads are often used instead of separate processes. Starting a new thread is much faster and uses far fewer system resources than starting a new process. Moreover, separate threads can communicate more easily with each other than separate processes. Many better modern kernels and various utilities, for example those in Solaris, are highly threaded. Typically, database managers, transaction processors, network protocol programs, GUIs and server code in the kernel are multithreaded. Good candidates for multithreading are: servers, programs with many independent tasks, programs with repetitive tasks, and "vectorizable" programs. Bad candidates are: simple programs, ones where tasks are tightly interconnected, or ones with very independent tasks (write as separate programs instead). The danger in multithreading is the temptation to write "bloatware" such as the leading web browsers and office suites.
The reasons for multithreading a program are:
Threads exist and can be implemented at several levels.
User thread libraries are faster to set up than LWP's and may run faster because no system calls are used. Functionality is implemented at user level instead of at the system call level. Asynchronous difficulties are hidden in the library and the user has a relatively simple interface to deal with. Once the application is written, if desired, it is fairly easy to change the application to use LWP's instead.
A process can have several underlying LWP's. Several user threads may be multiplexed over a few LWP's. Some threads (for example, a thread associated with a mouse) can be run at higher priority that other threads.
There are system programming problems with threads:
fork( )
- should the child process have
a duplicate of each thread or just of the calling thread (assuming an exec is
pending)?
In Solaris fork( )
duplicates all threads whereas
fork1( )
duplicates just the calling thread.
With POSIX threads only the calling thread is duplicated.
To control access to global variables and shared resources, various synchronization primitives are used:
POSIX Threads |
pthread_create
(start_function, arg structure)
creates a thread, invoking start_function
and passing data via arg structure
.
pthread_exit
(
)
or a return from start_function
ends a thread. exit
must not be used as it will
kill the entire process, not just the current thread.
pthread_cancel
(
)
kills some thread.
pthread_join
(
)
allows one thread to wait for another.
pipe
since
pipe
is an inter process communication call and is not needed.
Similarly exec
has no analogue as an
exec
would replace the code for all threads and typically
threaded code is self contained.
Process call | Thread call |
fork |
pthread_create |
exit |
pthread_exit |
kill |
pthread_cancel |
waitpid |
pthread_join |
CreateThread
,
_beginthreadx
,
or _beginthread
;
ExitThread
,
_endthreadx
,
or _endthread
;
TerminateThread
;
WaitForSingleObject
. These are analogues to
NT's CreateProcess
and
ExitProcess
.
Last update: 2001 April 9