app:
互斥量:
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_lock(&mutex);
pthread_mutex_trylock(&mutex);
pthread_mutex_unlock(&mutex);
自旋锁:
pthread_spin_t spin;
pthread_spin_init(&spin, 0);
pthread_spin_lock(&spin);
pthread_spin_trylock(&spin);
pthread_spin_unlock(&spin);
加锁一定要避免死锁:
常见的死锁有:
1. ABBA
2. 进程自己递归加锁
加锁的粒度:
不能太大,太大有可能起步到保护作用;会降低程序的执行效率。
加锁是一种工程师的自愿工作,如果要加锁,一开始就要考虑。
kernel:
解决竞争实现同步的机制:
1. 原子操作
int i = 2; /*global*/
A process B process
//i++; i++;
ldr r0,[r1] ldr r0,[r1]
add r0,#1 add r0,#1
str r0,[r1] str r0,[r1]
i = 3; i = 4;
原子变量替换整形变量。
原子变量:
//int i = 2;
atomic_t v = ATOMIC_INIT(2);
原子操作函数接口:
//i += 3;
atomic_add(3, &v);
atomic_add_return();
atomic_add_negative();
atomic_inc();
atomic_inc_and_test();
atomic_inc_return();
2. 信号量
信号量属于睡眠锁,可以指定锁的持有者的个数。
实例化:
struct semaphore sema;
初始化:
sema_init(&sema, 1);
加锁解锁:
down()/up();
如果当前进程获得信号量暂时拿不到,睡。
3. 互斥量
睡眠锁
struct mutex;
使用互斥量锁的步骤:
实例化:
struct mutex mutex;
初始化:
mutex_init(&mutex);
加锁/解锁
mutex_lock(&mutex);/mutex_unlock(&mutex);
4. 自旋锁
非睡眠锁
实例化:
spinlock_t spin;
初始化:
spin_lock_init(&spin);
加锁:
//进程和进程
spin_lock(&spin);
spin_unlock(&spin);
//进程和进程,进程和中断处理函数的竞争
spin_lock_irqsave();
spin_unlock_irqrestore();
spin_lock_bh();
spin_unlock_bh();