https://www.cnblogs.com/lidabo/archive/2012/08/15/2640204.html
https://blog.csdn.net/QIANGWEIYUAN/article/details/88792621
https://blog.csdn.net/xy_cpp/article/details/81910513
http://www.360doc.com/content/17/0506/10/8392_651520213.shtml
Remzi的OSTEP 操作系统导论
本文主要分为两块,第一块介绍互斥,第二块是C++ 11中的多线程编程学习笔记。阅读时间大约40分钟。
多线程编程
互斥、原子操作及硬件原语
为什么需要互斥?为什么有临界区?
因为中断随时可能发生,而中断必不可少
。
1.关闭中断
最早为了实现互斥,使用控制中断的方法——在临界区关闭中断。
很好理解,处理器自闭了,和每个进程(线程)轮番上演吊死在一棵树上的戏码。
缺点:特权滥用,害怕恶意进程,不支持多处理器,以及,中断很重要!(比如磁盘完成了读取请求但是由于没有中断,等待读取的进程无从得知这一事实)
2.test-and-set
测试并设置指令(test-and-set)——一种原子交换,自旋性能损耗大,有硬件支持,不会因为不可预知的中断导致失去原子性和正确性
int TestAndSet(int *old_ptr,int new)//原子性的把旧值变为新值,并且返回旧值
{
int old=*old_ptr;
*old_ptr=new;
return old;
}
typedef struct lock_t
{
int flag;
}lock_t;
void init(lock_t *lock)
{
lock->flag=0;
}
void lock(lock_t *lock)
{
while(TestAndSet(&lock->flag,1)==1) //还有一种错误写法 :while(lock_t->flag==1) ; lock_t->flag=1;
;// 自旋
}
void unlock(lock_t *lock)
{
lock->flag=0;
}
3.compare-and-swap
比较并交换(SPARC系统上是compare-and-swap,x86上是compare-and-exchange)
只需要将TestAndSet函数换为以下函数即可:
int CAS(int *old_ptr,int expected,int new)
{
int old=*old_ptr;
if(old==expected) //本行就是比test-and-set添加的部分
*old_ptr=new;
return old;
}
4.load-link and store-conditional
连接的加载和条件式存储指令
int LoadLinked (int *ptr)
{
return *ptr;
}
int StoreConditional(int *ptr,int value)
{
if(加载的地址在这段期间都没有更新过)
{
*ptr=value;
return 1;
}
else
return 0;
}
void lock(lock_t *lock)
{
while(1)
{
while(LoadLinked(&lock->flag)==1) //锁目前不可用就自旋
;
if(StoreConditional(&lock->flag,1)==1)//如果说成功把*ptr更新为1,那么获取锁成功,否则失败
return;
}
}
void unlock(lock_t *lock)
{
lock->flag=0;
}
1、2、3、4均是硬件原语的C语言伪代码,它们实现了正确性&