持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
2.41 单核机器上写多线程程序,是否要考虑加锁,为什么?
参考回答
在单核机器上写多线程程序,仍然需要线程锁。
原因:因为线程锁通常用来实现线程的同步和通信。在单核机器上的多线程程序,仍然存在线程同步的问题。因为在抢占式操作系统中,通常为每个线程分配一个时间片,当某个线程时间片耗尽时,操作系统会将其挂起,然后运行另一个线程。如果这两个线程共享某些数据,不使用线程锁的前提下,可能会导致共享数据修改引起冲突。
2.42 说说多线程和多进程的不同?
参考回答
(1)一个线程从属于一个进程;一个进程可以包含多个线程。
(2)一个线程挂掉,对应的进程挂掉,多线程也挂掉;一个进程挂掉,不会影响其他进程,多进程稳定。
(3)进程系统开销显著大于线程开销;线程需要的系统资源更少。
(4)多个进程在执行时拥有各自独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段;但每个线程拥有自己的栈段和寄存器组。
(5)多进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈;多线程切换时只需要切换硬件上下文和内核栈。
(6)通信方式不一样。
(7)多进程适应于多核、多机分布;多线程适用于多核
2.43 简述互斥锁的机制,互斥锁与读写的区别?
参考回答
-
互斥锁机制:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒。
-
互斥锁和读写锁:
(1) 读写锁区分读者和写者,而互斥锁不区分
(2)互斥锁同一时间只允许一个线程访问该对象,无论读写;读写锁同一时间内只允许一个写者,但是允许多个读者同时读对象。
答案解析
原理详解:
互斥锁其实就是一个bool型变量,为true时表示锁可获取,为false时表示已上锁。这里说的是互斥锁,其实是泛指linux中所有的锁机制。
我们采用互斥锁保护临界区,从而防止竞争条件。也就是说,一个线程在进入临界区时应得到锁;它在退出临界区时释放锁。函数 acquire() 获取锁,而函数 release() 释放锁,如图 :
每个互斥锁有一个布尔变量 available,它的值表示锁是否可用。如果锁是可用的,那么调用 acquire() 会成功,并且锁不再可用。当一个线程试图获取不可用的锁时,它会阻塞,直到锁被释放。
按如下定义 acquire():
acquire() { while (!available); /* busy wait */ available = false; }
按如下定义release():
release() { available = true; }