目录
概要:
- 什么是同步,什么是异步,什么是互斥?
异步:异步是现在操作系统的共有的基本特性。熟悉计算机操作系统的小伙伴们应该知道,计算机的发展经过好几个阶段,这里不长篇大论,简单讲讲,计算机以前不支持多进程运行的,那个时候计算机同一时间段内只能处理一个作业,直到整个作业结束才可以执行下一个作业,这里会出现问题,比如说这台计算机用cpu计算任务需要二十秒,而将任务结果用打印机打印出来需要一分钟,按照这种计算机的特性,cpu在打印机结束之前不能用于别的进程。按照刚才的例子就是cpu空闲了60-20=40秒,要知道cpu那么贵,这是不能忍的。随着发展,到分时系统的出现解决了这个问题,所谓分时系统就是cpu可以同时进行多个任务的处理,具体做法就是用时钟中断控制每一个进程的运行时间,简单来说就是轮流运行,每个进程运行时间段是固定的,这个时间段很小,这样可以保证cpu大多数时候都在多个进程之间来回切换,提高了cpu利用率。这种多进程共同执行的现象就是异步。
一:异步会带来什么问题?
加入在第一个时间片段A进程申请打印机资源,然后A进程放弃cpu资源让给B,而A去用打印机了。此时B进程在自己的时间片段内也申请了打印机。这时打印机就会打印出A B两个进程的运算结果,这就是异步带来的资源分配问题。
二: 如何解决?
我们可以用一个钥匙,谁要用打印机先出示钥匙,没有钥匙对不起,打印机拒绝执行,这个思想就是说对于共享的临界资源在同一时刻必须只能一个进程访问,这就叫互斥,也就是互斥访问。
说了这么多,先总结两个概念:
- 异步:系统本身的特性,后来在进程的基础上操作系统有引入了线程,不过概念差不多,多进程之间异步操作,多线程之间也是异步操作。异步就是轮流去申请cpu资源。
- 互斥解决解决异步带来的公共资源状态不一致特性,让临界资源同一时刻只能由有一个线程访问。
三:说了这么多什么是同步?
同步:解决程序之间因为并发而存在的异步性 。 这句话的意思就是,因为异步会让线程之间轮流获取时间片执行,谁在下一个时间片段获取到cpu是不确定,又系统进行分配。那么加入此有这么一个需求,B线程必须在A线程运行结束之后才可以执行,因为B线程的执行依赖A线程的结果。这就要求先A后B,这种顺序性的保证就叫做同步。
到这里,估计你有点迷糊,这同步和互斥怎么看着差不多啊? 没错,其实同步和互斥原理确实一样,都是通过钥匙来强行控制线程执行的。
四:总结
所以说,java多线程操作就是用互斥保证临界资源的安全。也可以这么说,java多线程操作就是保证线程之间对于临界资源同步性。 细微区别就是,同步强调A->B绝对顺序,而互斥一般是说这个资源必须保证安全,但是对于A进程B进程谁先用没有概念上的限制。 所以说同步互斥底层原理都是一样的,都是用原子特性(一般是硬件实现的 p v 操作)保证临界资源的安全,因为同步是说有顺序的,一般对于线程通信我们说成同步操作。 而无序的称为互斥操作。
五:同步例子
下面是一个同步操作,你也可以说是java多线程安全的互斥操作(不严谨,也不错)。
https://blog.csdn.net/a907691592/article/details/98341001 (引用的别人的例子)
如果两个线程之间有依
赖关系,线程之间必须进行通信,互相协调才能完成工作。
例如有一个经典的堆栈问题,一个线程生成了一些数据,将数据压栈;另一个线程消费了这些数据,
将数据出栈。这两个线程互相依赖,当堆栈为空时,消费线程无法取出数据时,应该通知生成线程添
加数据;当堆栈已满时,生产线程无法添加数据时,应该通知消费线程取出数据。wait noitfy两个方法是每一个对象都有的方法,Object最上层的方法,可以对当前对象进行控制。
补充:距离这篇文章的完成过去了一年,今天偶尔翻到,在这里补充几句。上面的wait 和notify 其实就是线程之间的通信。java线程池中的callable 大量用了这块知识,Future封装了线程的返回数据,实现线程之间的异步操作。
篇幅有限:实在不理解的建议看看操作系统。