线程间如何同步?

同步解决的多线程操作共享资源的问题,目的是不管线程之间的执行如何穿插,最后的结果都是正确的。

我们前面知道线程和进程的关系:线程是进程当中的⼀条执⾏流程。所以说下面的一些同步机制不止针对线程,同样也可以针对进程。

临界区:我们把对共享资源访问的程序片段称为临界区,我们希望这段代码是互斥的,保证在某时刻只能被一个线程执行,也就是说一个线程在临界区执行时,其它线程应该被阻止进入临界区。

os-48a5b48b-2474-4460-ac5b-9502883b353f.png

临界区不仅适用于线程,同样适用于进程。

临界区同步的一些实现方式:

使用加锁和解锁操作可以解决并发线程/进程的互斥问题。

任何想进入临界区的线程/进程,必须先执行加锁操作。如果加锁操作成功,线程/进程可以进入临界区;在完成对临界资源的访问后,再执行解锁操作,释放该临界资源。

加锁和解锁可以针对临界区对象,也可以只是一个简单的互斥量。例如,互斥量的值为0表示无锁,为1表示加锁。

根据锁的实现方式不同,可以分为忙等待锁无忙等待锁

  • 忙等待锁:加锁失败的线程/进程会不断尝试获取锁,也被称为自旋锁。它会持续占用CPU。
  • 无忙等待锁:加锁失败的线程/进程会进入阻塞状态,放弃CPU,并等待被调度。
  1. 信号量

信号量是操作系统提供的一种协调共享资源访问的方法。

通常,信号量表示资源的数量,对应的变量是一个整型(sem)变量。

操作系统提供了两个原子操作的系统调用函数来控制信号量:

  • P操作:将sem减1。相减后,如果sem < 0,则进程/线程进入阻塞等待;否则继续执行。P操作可能会阻塞。
  • V操作:将sem加1。相加后,如果sem <= 0,则唤醒一个等待中的进程/线程。V操作不会阻塞。

P操作用于进入临界区之前,V操作用于离开临界区之后。这两个操作必须成对出现。

标签: java, Java面试题, 操作系统, Java问题合集, Java编程, Java问题精选, Java常见问题, 操作系统面试题