进程或线程终止是否会释放锁

线程锁用于解决多线程环境中临界资源的安全访问问题,如在抢票程序中防止tickets变为负数。锁的原子性确保了在加锁和解锁过程中不会出现数据不一致。当线程A拿到锁并访问资源时,即使被切换,其他线程也无法访问。线程在终止时,若持有锁,应正确释放以避免死锁,可以通过清理处理程序实现。
摘要由CSDN通过智能技术生成

线程锁的必要性

比如一个多线程抢票程序,tickets作为临界资源,所有的线程都要对它进行判断ticket是否大于0,以及ticket–的操作。用ticket–操作举例,虽然他看起来是一行C语言的代码,但是实际上它的底层汇编经历了三个阶段,分别是load命令,减法命令,以及store命令。

由于线程是不断在切换的,因此一个线程在执行完load命令之后,很可能还没来得及做减法或者写回操作,就被切走了。CPU开始执行下一个线程。所以就会出现tickets为负数的情况。

锁的原理

我们发现,tickets是所有线程都可以看到的资源,因此是临界资源。而锁也是所有线程都可以看到的资源,那么为什么它不会造成线程安全问题呢?这是因为加锁和解锁的过程是原子性的。它的关键在于:只使用一条汇编,就将内存中的数据和CPU寄存器中的数据进行交换了。

进程终止

进程终止时系统不会自动释放所持有的互斥锁、读写锁和Posix信号量,进程终止时内核总是自动清理的唯一同步锁类型是fcntl记录锁。System V信号量,应用程序可以选择进程终止时内核是否自动清理某个信号量。

要理解这一过程,首先要理解上下文数据的概念。其实就是线程被切换后它的PCB中保存着执行的数据。

当线程A到来时,假设它要抢锁,目前其他线程没有它来的快。它的寄存器al的数据现在是0,执行交换操作,将内存中mutex的值交换给A的寄存器al中,此时线程A的al值为1,内存中mutex的值为0。

当线程A被切换走时(是带着上下文数据1一起被切走的),线程B到来,它的al寄存器中的值为0(线程设置的是自己的上下文数据,互相不冲突),进行交换mutex的值和al寄存器的值(0和0交换),最终B拿到的值是0,发生挂起等待。此时就可以根据每个线程的al中寄存器的值判断是哪一个线程抢到了锁,从而只允许该线程访问临时资源。当A访问完资源后,释放锁,唤醒等待的线程,并将mutex的值置为1。

注意,拿到锁的A在访问临时资源的时候还是会被切换的,只不过其他线程此时无法访问临时资源。

站在其他线程的视角,要么A没有申请锁不能访问临界资源,要么A申请锁了访问了临界资源。因此线程A访问临界资源的动作具有原子性。

线程终止

(1)一个线程也可以在持有某个互斥锁期间终止,自己调用pthread_exit或被另一个线程取消。如果线程调用pthread_exit资源终止时,这时它应该知道自己还持有一个互斥锁(对于程序员来说),如果是被另一个线程取消的情况,线程可以安装清楚处理程序(pthread_cleanup_push),在被取消时调用来释放相应的锁。

(2)对于线程意外操作导致进程终止的情况,就和进程终止时相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李小白20200202

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值