1、相关背景知识
临界资源 | 多线程、多执行流共享的资源,就叫做临界资源 |
临界区 | 每个线程内部,访问临界资源的代码 |
互斥 | 在任何时刻,保证有且只有一个执行流进入临界区,访问临界资源,对临界资源起到保护作用 |
原子性 | 不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么没开始。(只要开始,必须完成了才能中断) |
2、多线程工作的问题(抢票样例)
1、首先存在初始为100的票数tickets。
2、然后新建4个线程,进行抢票。
3、为了让tickets成为临界资源,将tickets初始为全局的。
int tickets = 100; // 票数
void Job(const std::string &name)
{
while (true)
{
if (tickets > 0)
{
/*抢票*/
usleep(1000); // 1ms -> 抢票时间
printf("who : %s , get a ticket , remain tickets : %d\n", name.c_str(), tickets); // 抢票
tickets--;
}
else
{
break;
}
}
}
int main()
{
Thread t1("thread-1", Job);
Thread t2("thread-2", Job);
Thread t3("thread-3", Job);
Thread t4("thread-4", Job);
t1.Start();
t2.Start();
t3.Start();
t4.Start();
t1.Join();
t2.Join();
t3.Join();
t4.Join();
return 0;
}
查看运行结果:
本来当remain tickets为0的时候,就不应该进入抢票逻辑了。
但是输出结果明显不对劲,票数都变为负数了,还在抢票。
为什么会出现这种情况呢?
多个线程并发的操作临界资源,就会带来一些问题。
因此,多个线程的临界区代码,必须具有互斥行为。
为了保证这个互斥行为,就引出了互斥量(即,加锁)。
3、锁
3.1、认识锁和接口
pthread_mutex_t | pthread库提供的互斥锁类型 |
PTHREAD_MUTEX_INITIALIZER | 如果锁是全局的或者静态的,可以直接mutex = PTHREAD_MUTEX_INITIALIZER进行初始化,并且最后不需要销毁 |
int pthread_mutex_init(pthread_mutex *restrict mutex, const pthread_mutexattr_t *restrict attr); | 初始化锁。 restrict mutex:就是需要初始化的锁。 restrict attr:表示设置锁的属性,一般置空即可。 |
int pthread_mutex_destroy(pthr |