P5 并发控制1:互斥
1:36 互斥问题理解
吧线程想象成人,吧共享内存想象成物理世界。线程不想被别人打断地做一件事
3:30 共享内存上的互斥
互斥锁救回了原子性(理解为厕所包间)
8:48 怎么样在共享内存上实现互斥
30:48 实现互斥:软件不够(仅仅通过共享内存比较复杂),结合硬件
38:44 x86原子操作的例子:lock指令前缀
#include "threads.h"
#define PREFIX "lock"
long sum;
void do_sum(){
for(int i=0;i<10000000;i++){
asm volatile( "lock addq $1,%0":"=m"(sum));
}
}
void print(){
printf("sum=%ld\n",sum);
}
int main(){
for(int i=0;i<4;i++)
create(do_sum);
join(print);
}
但是运行时间较长
40:36 X86原子操作:xchg
看成两个人A、B上厕所,每个人一把钥匙一各标签,全局变量为一张桌子,初始值放了把钥匙,A要上厕所,把标签和桌上的钥匙交换,拿钥匙进厕所,此时B就一直是在吧自己的标签和A的标签做交换
将值传入对应的内存地址
int xchg(volatile int *addr,int newval){
int result;
asm volatile ("lock xchg %0,%1":"+m"(*addr),
"=a"(result)
:"1"(newval)
:"cc");
return result;
}
43:29 实现互斥:自旋锁
int table = KEY;
void lock() {
while (1) {
int got = xchg(&table,NOTE); //把自己的东西和桌上的东西进行交换,无论桌上是什么,返回值是当期桌上的东西
if (got == KEY)
break;
}
}
void unlock() {
xchg(&table,KEY);
}
改进:
int locked = 0;
void lock(){
while (xchg(locked, 1)) ;
}
void unlock(){
xchg(&locked,0 );
}
自旋锁实现例程:
#include "threads.h"
#include <stdint.h>
#include <stdatomic.h>
typedef struct spinlock {
volatile int locked;
}spinlock_t;
void spin_init(spinlock_t *lk){
lk->locked = 0;
}
int xchg(volatile int *addr,int newval){
int result;
asm volatile ("lock xchg %0,%1"
:"+m"(*addr),
"=a"(result)
:"1"(newval)
:"cc");
return result;
}
void spin_lock(spinlock_t *lk){
while (xchg(&lk->locked,1));
}
void spin_unlock(spinlock_t *lk){
xchg(&lk->locked,0);
}
spinlock_t lk;
long volatile sum = 0;
void do_sum() {
for(int i=0;i<10000000;i++){
spin_lock(&lk);
sum++;
spin_unlock(&lk);
}
}
void print(){
printf("sum=%ld\n",sum);
}
int main(){
spin_init(&lk);
for(int i=0;i<4;i++)
create(do_sum);
join(print);
}
47:50 另一种原子操作:RISC-V
62:30 数据竞争