20200725——操作系统 线程间通信的方式
前言
复习一下,进程间通信的方式有
1)管道
2)信号量
3)消息队列
4)共享内存
5)socket远程调用
volatile关键字
/**
* @Classname Test1
* @Description TODO
* @Date 2020/7/25 23:26
* @Created by mmz
*/
public class Test1 {
static volatile boolean flag = true;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
int index = 10;
while(true){
if(flag){
if(index !=0){
System.out.println("a");
flag = false;
index--;
}
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
while(true){
int index = 10;
if(!flag){
if(index != 0){
System.out.println("b");
flag = true;
index--;
}
}
}
}
});
thread1.start();
thread2.start();
}
}
这种方式采用volatile关键字来实现线程间相互通信是使用共享内存的思想,多线程监听一个变量,当这个变量发生改变的时候,线程能够感知并执行相应的业务。
当然也可以打印多个字母,不限制的。三个线程打印abc
/**
* @Classname Test2
* @Description TODO
* @Date 2020/7/25 23:35
* @Created by mmz
*/
public class Test2 {
static volatile int number = 1;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
int index = 10;
while(true){
if(number == 1){
if(index != 0){
System.out.println("a");
number = 2;
index--;
}
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
int index = 10;
while(true){
if(number == 2){
if(index != 0){
System.out.println("b");
number = 3;
index--;
}
}
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
int index = 10;
while(true){
if(number == 3){
if(index != 0){
System.out.println("c");
number = 1;
index--;
}
}
}
}
});
thread1.start();
thread2.start();
thread3.start();
}
}
使用Object类的notify和wait
/**
* @Classname Test3
* @Description TODO
* @Date 2020/7/25 23:40
* @Created by mmz
*/
public class Test3 {
static Object lock = new Object();
static int number = 0;
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
int index = 10;
while(index != 0){
if(number == 0){
System.out.println("a");
number++;
index--;
try {
lock.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
try{
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
int index = 10;
while(index != 0){
if(number == 1){
System.out.println("b");
number++;
index--;
try {
lock.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
try{
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
});
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock){
int index = 10;
while(index != 0){
if(number == 2){
System.out.println("c");
number = 0;
index--;
try {
lock.notifyAll();
}catch (Exception e){
e.printStackTrace();
}
}
try{
lock.wait();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
});
thread1.start();
thread2.start();
thread3.start();
}
}
声明一个Object类型的锁,sychronized直接上锁。进行业务逻辑判断。
工具类JUC下面的CountDownLatch
在aqs学习的时候,我们就提及到过CountDownLatch基于AQS框架。AQS并不陌生,一个state判断当前状态,一个共享线程判断当前是谁占有资源,一个CLH虚拟双向队列线程排位。
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.util.concurrent.CountDownLatch;
/**
* @Classname Test4
* @Description TODO
* @Date 2020/7/25 23:55
* @Created by mmz
*/
public class Test4 {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(2);
Thread threa1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("C等待其他人");
try{
countDownLatch.await();
}catch (Exception e){
e.printStackTrace();
}
System.out.println("C开始工作");
}
});
Thread threa2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("A开始工作");
countDownLatch.countDown();
}
});
Thread threa3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("B开始工作");
countDownLatch.countDown();
}
});
threa1.start();
threa2.start();
threa3.start();
}
}
但是这个代码好像就不能无限循环了,只能执行一次。其他线程都在执行countDown方法,让一开始定的计数器-1,只有await方法会在为0的时候调用,无法多线程一起被唤醒,相对于notifyAll和wait
还有ReentranLock中的condition
暂时不太了解,看了代码感觉有些复杂。不如wait和notifyAll
线程间同步的方式
互斥量 Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问;当前拥有互斥对象的线程处理完任务后必须将互斥对象交出,以便其他线程访问该资源;
信号量 Semphare:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
事件(信号),Wait/Notify:允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。事件分为手动重置事件和自动重置事件。通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
个人总结,关于进程与线程
进程是对运行时程序的封装,是系统对资源调度和分配的基本单位,实现了操作系统的并发。
线程是进程的子任务,一个进程至少有一个线程。线程基于进程存在。
进程在执行的过程中有独立的内存单元,多个线程共享进行的内存。
本文地址:https://blog.csdn.net/qq_36344771/article/details/107587119