1.同步
就是通过Synchronized关键字来进行同步访问控制,确保谁拿到了相应的锁才能执行相应的操作
本质上就是共享内存式的通信,这个共享内存在java的内存模型中就是主内存,相当于通过主内存的数据进行线程通信。因Synchronized解锁时会将工作内存中的数据刷新到主内存中,Synchronized加锁时会将工作内存中的值清空从主内存读。多个线程访问同一变量,谁拿到了锁谁就去访问。
2.while轮询
假设我们添加线程向一个List中存入元素(一直存入),判断线程判断如果存入的元素达到了3个,我们就退出存入元素的线程,转而进入另一个等待它存入三个元素的线程。那么这个等待的线程我们使用while轮询list集合中是否达到了三个,如果到了三个我们就进行下一步,没有就一直轮询,
问题:
1.我们发现判断的线程如果没达到它的要求,cpu执行到它时就一直空转,白白浪费
2.这个方法还有一个问题,我们没办法保证可见性,也就是说假设当加入元素的线程到达了3个,但是此时元素数量3只是处于工作内存中,那么在它将工作内存中的3刷新到共享内存中的这段时间中可能又加入了新的元素,加入后等待线程取到值,可是这时候已经大于3了,所以程序会出现问题。
3.wait/notify机制
这是一个Object里的方法,两个方法的作用就是沉睡和唤醒,当我们的等待线程发现没有达到想要的条件我们就沉睡它,此时另一个线程来加入元素,当元素数量达到了3 ,我们可以唤醒等待线程,告诉他你的条件达到了,你继续执行吧
问题:如果说添加元素的线程一下添加了3个,进行了唤醒操作,但是等待线程还没运行到wait,这时产生了次空唤醒。当等待线程执行到wait之后沉睡,因为它要依靠添加元素的线程唤醒,但是添加元素的线程已经进行了唤醒,因此会一直沉睡。
4.消息管道:
就是通过一条管道传输线程之间通信的消息。