Operating System: Three Easy Pieces --- Locks (Note)
2015-11-22 11:22
555 查看
From the introduction to concurrency, we saw one of the fundamental problems in concurrent
programming: we could like to execute a series of instructions atomically, but due to the
presence of interrupts on a single processor or multiple threads executing on multiple processors
concurrently, we couldn't. In this chapter, we thus attack this problem directly, with the
introduction of something referred to as a lock. Programmers annote source code with locks,
putting them around critical sections, and thus ensure that any such critical section executes as if
it were a single atomic instruction.
Locks: The Basic Idea
As an example, assume our critical section looks like this, the canonical update of a shared
variable:
Of course, other critical sections are possible, such as adding an element to a linked list or other
more complex updates to shared structures, but we will just keep to this simple example for now.
To use a lock, we add some code around the critical section like this:
A lock is just a variable, and thus to use one, you must declare a lock variable of some kind (such
as mutex above). This lock variable or just lock for short holds the state of the lock at any instant
in time. It is either available or unlocked or held, and thus exactly one thread holds the lock and
presumably is in a critical section. We could store other information in the data type as well, such
as which thread holds the lock, or a queue for ordering lock acquisition, but information like that
is hidden from the user of lock.
The semantics of the lock() and unlock() routines are simple. Calling the routine lock() tries to
acquire the lock; if no other thread holds the lock (i.e.,it is free), the thread will acquire the lock
and enter the critical section; this thread is sometimes said to be the owner the lock. If another
thread then calls lock() on that same lock variable (mutex in this example), it will not return while
the lock is held by another thread; in this way, other threads are prevented from entering the
critical section while the first thread that holds the lock is in there.
Once the owner of the lock calls the unlock(), the lock is now available (free) again. If no other
threads are waiting for the lock (i.e., no other thread has called lock() and is stuck therein), the
state of the lock is simply changed to free. If there are waiting threads (stuck in lock()), one of
them will eventually notice or be infromed of this change of the lock's state, acquire the lock, and
enter the critical section.
Locks provide some minimal amount of control over scheduling to programmers. In general, we
view threads as entities created by the programmers but scheduled by the OS, in any fashion
that the OS chooses. Locks yield some of that control back to the programmer; by putting a lock
around a section of code, the programmer can guarantee that no more than a single thread can
ever be active within that code. Thus locks help transfrom the chaos that is traditional OS
scheduling into a more controlled way.
programming: we could like to execute a series of instructions atomically, but due to the
presence of interrupts on a single processor or multiple threads executing on multiple processors
concurrently, we couldn't. In this chapter, we thus attack this problem directly, with the
introduction of something referred to as a lock. Programmers annote source code with locks,
putting them around critical sections, and thus ensure that any such critical section executes as if
it were a single atomic instruction.
Locks: The Basic Idea
As an example, assume our critical section looks like this, the canonical update of a shared
variable:
balance = balance + 1;
Of course, other critical sections are possible, such as adding an element to a linked list or other
more complex updates to shared structures, but we will just keep to this simple example for now.
To use a lock, we add some code around the critical section like this:
lock_t mutex; ... lock(&mutex); balance = balance + 1; unlock(&mutex);
A lock is just a variable, and thus to use one, you must declare a lock variable of some kind (such
as mutex above). This lock variable or just lock for short holds the state of the lock at any instant
in time. It is either available or unlocked or held, and thus exactly one thread holds the lock and
presumably is in a critical section. We could store other information in the data type as well, such
as which thread holds the lock, or a queue for ordering lock acquisition, but information like that
is hidden from the user of lock.
The semantics of the lock() and unlock() routines are simple. Calling the routine lock() tries to
acquire the lock; if no other thread holds the lock (i.e.,it is free), the thread will acquire the lock
and enter the critical section; this thread is sometimes said to be the owner the lock. If another
thread then calls lock() on that same lock variable (mutex in this example), it will not return while
the lock is held by another thread; in this way, other threads are prevented from entering the
critical section while the first thread that holds the lock is in there.
Once the owner of the lock calls the unlock(), the lock is now available (free) again. If no other
threads are waiting for the lock (i.e., no other thread has called lock() and is stuck therein), the
state of the lock is simply changed to free. If there are waiting threads (stuck in lock()), one of
them will eventually notice or be infromed of this change of the lock's state, acquire the lock, and
enter the critical section.
Locks provide some minimal amount of control over scheduling to programmers. In general, we
view threads as entities created by the programmers but scheduled by the OS, in any fashion
that the OS chooses. Locks yield some of that control back to the programmer; by putting a lock
around a section of code, the programmer can guarantee that no more than a single thread can
ever be active within that code. Thus locks help transfrom the chaos that is traditional OS
scheduling into a more controlled way.
相关文章推荐
- Linux查看CPU个数
- centos6.5安装apache2.x并修改默认80端口
- 01 docker 安装操作
- (转)RabbitMQ 集群与高可用配置
- OpenGLES 3.0
- iPhone开发基础教程笔记(十二)--第十二章 使用Quartz和OpenGL绘图
- opkg 不能更新和安装openwrt软件的方法
- 00.Python manage.py shell和 Python的分析
- opencv 报错:fatal error C1083: 无法打开包括文件: “stdafx.h”: No such file or directory
- OpenCV摄像头人脸识别
- opencv学习笔记(二十一)——阈值操作
- 如何得到linux的pagesize
- Linux常用环境安装步骤
- linux虚拟机网卡启动失败问题处理
- Linux Advance--可重入的getenv
- IRelationalOperator空间关系接口简介
- CentOS6.2使用yum安装LAMP及phpMyadmin
- linux常用命令
- 继续收集Docker书
- 练习--LINUX进程间通信之消息队列MSG