线程互斥 \color{orange}{\huge{线程互斥}} 线程互斥
R
a
c
e
C
o
n
d
i
t
i
o
n
(
竞态条件
)
Race \space Condition(竞态条件)
Race Condition(竞态条件)
产生不确定性现象的条件之一
\red{产生不确定性现象的条件之一}
产生不确定性现象的条件之一。
系统缺陷
\color{blue}系统缺陷
系统缺陷:运行的结果依赖于并发执行或者时间的顺序/时间。
A
t
o
m
i
c
O
p
e
r
a
t
i
o
n
(
原子操作
)
Atomic \space Operation(原子操作)
Atomic Operation(原子操作)
原子操作
\color{blue}{原子操作}
原子操作:指一次不存在任何中断或者失败的执行。进程使用原子操作可以减少变成竞态的概率。
线程相互竞争示例:
线程相互竞争示例:
线程相互竞争示例:
线程
A
\color{blue}线程A
线程A:
int i = 0;
while(i < 10)
i += 1;
printf("A wins!");
线程 B \color{blue}线程B 线程B:
i = 0;
while(i > -10)
i -= 1;
printf("B wins!");
i \color{red}i i是两个线程的共享变量,当两个线程运行的时候,因为对 i \red i i的操作不是原子操作,所以在翻译为机器代码的时候,可能出现竞态。 最后的胜利结果无法预知 \purple{最后的胜利结果无法预知} 最后的胜利结果无法预知。
满足进程 P i P_{i} Pi和 P j P_{j} Pj之间互斥的经典 基于软件 \red{基于软件} 基于软件的解决方法(基于进程 P i P_{i} Pi一方的算法):
int turn; //指示谁应该进入临界区
bool flag[]; //指示当前进程是否准备好了进入临界区
do
{
flag[i] = true; //当前的进程i准备好了进入临界区
turn = j; //但是真正轮到进入临界区的是进程j
while(flag[j] && turn == j); //当轮到进程j进入的时候并且j也准备好了,进程i循环等待
critical section //然后进程i进入临界区
flag[i] = false; //表示进程i没有准备好了
remainder section //进程i进入等待区间
}while(true)
B
a
k
e
r
y
算法
\color{olive}{Bakery算法}
Bakery算法(
N
N
N个进程的临界区互斥算法)
进入临界区之前,
进程收到一个数字
\red{进程收到一个数字}
进程收到一个数字。
所有进程中,得到数字
最小
\red{最小}
最小的进程进入临界区。
如果进程
P
i
P_{i}
Pi和
P
j
P_{j}
Pj接收了
相同
\red{相同}
相同的数字,那么如果
i
<
j
i < j
i<j,
P
i
P_{i}
Pi先进入临界区,否则
P
j
P_{j}
Pj先进入临界区。
编号的方案总是按照枚举的增加顺序生成数字。
抽象出一个 L o c k Lock Lock数据结构,结合 e x c h a n g e exchange exchange原子操作,实现多个线程对于临界区的访问管控。
int lock = 0; //共享数据(初始化为0)
线程Ti:
int key;
do{
key = 1;
while(key == 1)
exchange(lock,key);
critical section;
lock = 0;
remainder section;
}
整体流程:
\color{blue}{整体流程:}
整体流程:首先所有线程共享的
l
o
c
k
lock
lock初始化为
0
0
0。之后例如图中的线程
T
i
T_{i}
Ti,进入循环将每个线程配备的
k
e
y
key
key初始化为
1
1
1,之后进入
w
h
i
l
e
while
while循环,调用
e
x
c
h
a
n
g
e
exchange
exchange交换
l
o
c
k
lock
lock与
k
e
y
key
key内存中的数据。如果此时
l
o
c
k
lock
lock是
0
0
0,交换数据之后就会打破
w
h
i
l
e
while
while循环。此时该线程进入临界区,同时将
l
o
c
k
lock
lock置为
1
1
1,意为此时临界区有了线程访问,进行“锁住”。其他的线程无法进入。等到该线程访问完成之后,
l
o
c
k
lock
lock置为
0
0
0,下一个线程
e
x
c
h
a
n
g
e
exchange
exchange之后就可以进入了。
(
所有的线程都配有自己的
k
e
y
,但是所有的线程共用一个
l
o
c
k
\color{red}{所有的线程都配有自己的key,但是所有的线程共用一个lock}
所有的线程都配有自己的key,但是所有的线程共用一个lock)