munotes®

What a Thread Is

Get access to whole semester resourcesSemester Pass

Chapter Twenty-Six

Syllabus topic Module 1, "Processes - Threads - Overview"

Pages 101 to 104 of 452

In one line

A thread is one flow of execution inside a process, and a process may have many of them, all sharing its memory.

The form to write: a thread is the basic unit of processor utilisation. It has a thread id, a program counter, a register set and a stack of its own, and it shares its code, its data and its operating system resources with the other threads of the same process.

Why threads exist at all

Chapter twenty two showed two processes sharing memory, and it took four system calls and a great deal of care. Now ask the opposite question: what if two flows of execution wanted to share everything, all the time, by default?

That is a thread. And the reason to want it is that most real programs have several things to do at once on the same data:

  • a browser drawing a page while downloading the next image into the same document;
  • a word processor checking spelling while you type into the same text;
  • a web server answering two hundred requests out of the same cache.

Doing each of those with separate processes means copying or sharing the data explicitly. Doing them with threads means they are simply looking at the same variables.

What is shared and what is private

This is the table the topic reduces to and it is asked directly.

Shared by every thread of a processPrivate to each thread
the code, the text sectionthe program counter
the data section, the global variablesthe registers
the heapthe stack
open files and descriptorsthe thread id
the current directory, the userits signal mask, its errno
the process idits own place in a queue

Every thread has its own stack, and that is not optional. A stack holds the frames of the function calls in progress, and two threads are in different functions at the same moment, so they cannot share one. The stack is what makes a thread a thread.

A global variable is shared and a local variable is not, and that one sentence is where half the marks in this whole row are. A local variable lives on the thread's own stack; a global lives in the data section, which is shared. Chapter thirty four's race condition is exactly a shared global being changed by two threads, and Chapter thirty seven's fix is a lock around it.

The four benefits

MU's text book gives four and an examination asks for them by name.

  1. Responsiveness. A program can keep answering the user while part of it is busy or blocked.

A browser whose download thread is waiting for the network still scrolls.

munotes.in101

What a Thread Is

  1. Resource sharing. Threads share memory by default, with no system call and no setup. Two

processes must ask for shared memory; two threads already have it.

  1. Economy. Making a thread is far cheaper than making a process, and switching between two

threads of one process is cheaper than switching between two processes. Chapter sixteen's worked example says why: the memory mapping does not change.

  1. Scalability, also called utilisation of multiprocessor architectures. A process with

one thread can use one processor however many the machine has. Threads can run on all of them at once.

The fourth is the one that has changed in importance. When the four were first written, machines with more than one processor were rare. Every phone now has six or eight cores, and a single threaded program uses one of them.

Seeing threads on a real machine

A thread is not a process, but Linux shows both in the same table if you ask.

$ ps -o pid,nlwp,comm -p $$ --no-headers
      9    1 bash
$ grep Threads /proc/self/status
Threads:	1
$ ls -d /proc/$$/task/*
/proc/9/task/9

nlwp is the number of light weight processes, which is what Linux calls a thread, and Threads in the status file says the same thing. Each one has a directory of its own under task. A program with one thread has one of each, and Chapter twenty seven's program has ten.

Worked example: one job, three designs

A program must read a hundred files and count the words in each.

One process, one thread. Open a file, read it, count, next. While the disk fetches a block the program does nothing at all. On a two processor machine it uses one processor, and badly.

A hundred processes. Each counts one file. They genuinely run at once and use every processor. But each costs a full process creation, each has its own address space, and collecting the hundred answers needs inter-process communication: shared memory or a pipe per child, and Chapter twenty two or twenty three of work.

One process, several threads. Each thread takes a file from a shared list and adds its count to a shared total. They run at once, they use every processor, creation is cheap, and the answers are simply added into a shared variable with no communication machinery at all.

The third design is best and it is also the one that can go wrong in a way the other two cannot. "Adds its count to a shared total" is a race condition (Chapter thirty four) unless the addition is protected (Chapter thirty seven). Threads buy sharing and sell safety, and the whole of MU's process synchronisation row is the price.

munotes.in102

What a Thread Is

Distinctions that carry marks

ProcessThread
Address spaceits ownshared with its siblings
Creation costhigh: a whole address spacelow
Switching costhigh: the memory mapping changeslow: it does not
Communicationneeds shared memory or messagesordinary variables
Protection between themfull: one cannot touch the other's memorynone at all
If one crashes badlythe others survivethe whole process usually dies
Also calleda heavyweight processa lightweight process
Its own stackThe shared heap
Holdslocal variables, call frames, the return addressanything malloc gave out
Visible to other threadsno, in practiceyes
Growsper threadfor the whole process

What it does not mean

Threads do not make a program faster by themselves. They let it use more processors and stop waiting. A program that is limited by the disk gets nothing from more threads.

A thread is not a lightweight process in the sense of being a small process. It has no address space of its own at all. Linux calls it a light weight process because it implements both with one mechanism.

Threads do not remove the need for synchronisation. They create it. Two processes are protected from each other by the hardware. Two threads are protected from each other by nothing.

A single threaded program is not obsolete. It is simpler, it cannot race, and for most tasks it is the right answer.

Quick revision

  • A thread is the basic unit of processor utilisation: a thread id, a program counter,

registers and a stack of its own, sharing code, data, the heap and open files with its siblings.

  • Shared: text, data, globals, heap, open files, the process id. Private: program

counter, registers, stack, thread id.

  • A global variable is shared; a local variable is on the thread's own stack and is not.
  • Four benefits: responsiveness, resource sharing, economy, scalability on

several processors.

  • Threads are cheaper to make and cheaper to switch between than processes, because the address

space does not change.

  • Linux calls a thread a light weight process; ps -o nlwp, /proc/<pid>/status and

/proc/<pid>/task all count them.

  • Threads buy sharing and sell safety: everything in MU's synchronisation row is the price.

Test yourself

  1. Define a thread. The basic unit of processor utilisation, with its own thread id, program

counter, registers and stack, sharing its code, data and operating system resources with the other threads of the same process.

  1. What does a thread have of its own, and what does it share? Its own program counter,

registers, stack and thread id. It shares the text, the data section and globals, the heap, the open files and the process id.

  1. Why must each thread have its own stack? Because the stack holds the frames of the calls
munotes.in103

What a Thread Is

in progress, and two threads are inside different functions at the same moment.

  1. Name the four benefits of threads. Responsiveness, resource sharing, economy, and

scalability on a machine with several processors.

  1. Why is switching between two threads cheaper than between two processes? The address space

does not change, so the memory management hardware and its translation cache are untouched. 6. A program counts words in a hundred files using ten threads that add to one total. What is the danger? The shared total is changed by ten threads at once, which is a race condition. The addition must be protected by a lock.

  1. Is a local variable shared between threads? No. It lives on the calling thread's own

stack. A global variable is shared, because it lives in the shared data section.

munotes.in104

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself, or the past papers, for the same subject.

Issue
Done!