多线程同步异步,以及volatile关键字的作用

多线程同步异步,以及volatile关键字的作用
#多线程同步异步
多线程同步异步一直以来都是很热门讨论的话题,根据自己这段时间的学习总结下线程的同步异步问题
所谓同步直白了说就是让代码按照你写的顺序一行一行的执行,上一段代码执行完了返回了相对应的结果,根据结果再执行下一段代码,这就是所谓的同步。然而现实总是会出现一些不按照你的要求来的代码,上一段代码还没执行完,下一段代码就开始执行了,并没有按照你的顺序来执行,这时最产生了异步问题。最简单的应用,前端请求接口的时候,一个页面刚打开的时候会同时执行多个接口,接口返回的顺序可能并不是你所写的代码的顺序,如果想要按照你写的代码的顺序来执行,就需要用到同步了,今天主要说的是java后台多线程之间的同步异步以及关键字volatile的作用和用法。
先贴一段代码


```java
package episode.test15;

public class MyThread extends Thread{

	public static int count;
	
	 private static void addCount() {
		for(int i=0;i<100;i++) {
			count++;
		}
		System.out.println("count="+count);
	}
	
	public void run() {
		addCount();
	}

}
package episode.test15;

public class Run {
	public static void main(String[] args) {
		MyThread[] myThreadArray = new MyThread[100];
		for(int i=0;i<100;i++) {
			myThreadArray[i] = new MyThread();
		}
		for(int i=0;i<100;i++) {
			myThreadArray[i].start();
		}
	}

}

![在这里插入图片描述](https://img-blog.csdnimg.cn/20191027172200709.png)很明显看出来线程不是同步的,想要线程同步得再方法前加上synchronized关键字。不过synchronized关键字让方法同步了,却也是每次都得其他线程等待当前线程执行完成,才可以再执行下一个线程。
看下volatile关键字,先贴一段代码

```java
package episode.test14;

public class PrintString {
	private boolean isContinuePrint = true;

	public boolean isContinuePrint() {
		return isContinuePrint;
	}
	
	public void setisContinuePrint(boolean isContinuePrint) {
		this.isContinuePrint = isContinuePrint;
	}
	
	public void printStringMethod() {
		try {
			while(isContinuePrint) {
				System.out.println("run printStringMethod thread="+Thread.currentThread().getName());
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	

}
package episode.test14;

public class Run {

	public static void main(String[] args) {
		PrintString printStringService = new PrintString();
		printStringService.printStringMethod();
		System.out.println("我要停止它! stopThread="+Thread.currentThread().getName());
		printStringService.setisContinuePrint(false);	
	}

}

运行结果如下图所以:
在这里插入图片描述可以看到线程进入了死循环,“我要停止他”这段文字并未打印出来,这时候我们可以用多线程技术来解决这个问题代码如下

package episode.test14;

public class PrintString2 implements Runnable{

	private boolean isContentPrint = true;
	
	public boolean isContentPrint() {
		return isContentPrint;
	}

	public void setContinuePrint(boolean isContinuePrint) {
		this.isContentPrint = isContentPrint;
	}
	
	public void printStringMethod() {
		try {
			while(isContentPrint == true) {
				System.out.println("run printStringMethod threadName="+Thread.currentThread().getName());
				Thread.sleep(1000);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		printStringMethod();
		
	}
}
package episode.test14;

public class Run2 {

	public static void main(String[] args) {
		PrintString2 printStringService = new PrintString2();
		new Thread(printStringService).start();
		System.out.println("我要停止它!stopThread="+Thread.currentThread().getName());
		printStringService.setContinuePrint(false);
	}

}

运行结果如图所示:
在这里插入图片描述虽然system中的内容打印了出来,但是线程依然进入了死循环。我们对程序稍加改动,在变量前加上volatile看看结果如下:
贴上代码如下:

package episode.test14;

public class RunThread extends Thread{

	volatile boolean isRunning = true;
	
	public boolean AisRunning() {
		return isRunning;
	}
	
	public void setRuning(boolean isRunning) {
		this.isRunning = isRunning;
	}
	
	public void run() {
		System.out.println("线程启动进入run了");
		while(isRunning) {
			
		}
		System.out.println("线程被停止了!");
	}
	

}

结果如下:

在这里插入图片描述这是因为再未使用volatile关键字之前,变量private boolean isRunning=true存在于公共堆栈和私有堆栈中,每次改变变量值只改变了公共堆栈的值,而线程私有堆栈中的值却并未改变,所以线程一直处于死循环状态。加上volatile关键字之后,强制从公共堆栈中取值,因此线程可以跳出死循环。虽然volatile关键字增加了实力变量在多个线程间的可见想,但是volatile关键字并不是原子性,也就是说它并不能保证变量是同步的,是线程安全的。还是引用最开头的代码,在变量前加上volatile进行实验,结果如下与未加volatile关键字是一样的,因此若要实现同步线程安全,还是得在方法前加上synchronized关键字。综上所述,volatile关键字只是强制将变量从共有堆栈中取出来,并不能保证变量的原子性,想要保证变量的原子性还是要用synchronized关键字

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值