java多线程4:关键字volatile

java多线程4:关键字volatile

a.volatile关键字的作用:

使用volatile关键字增加了实例变量在多个线程之间的可见性。

如果没有使用这个关键字,出现如下现象:

这个时候就是私有堆栈和公共堆栈的值不同步。如果改变了公共堆栈中的值后,私有的依旧没有变化。如果添加了volatile关键字,这个变量就是和共有部分同步了。

b.案例解释:

package multiThread.volatilePack;

public class MyThread extends Thread {
	boolean b = true;

	public boolean isRunning() {
		return b;
	}

	public void setRunning(boolean b) {
		this.b = b;
	}

	public void run() {

		System.out.println("进入了running了");
		System.out.println(b + "   这个是进入循环前的b----------");
		while (b == true) {

			// System.out.println("进入循环");
		}

		System.out.println("线程被停止了");
	}

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
		try {
			Thread.sleep(10);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		myThread.setRunning(false);

		System.out.println("已经设置为false了");

	}

}

控制台:

如果我们对变量b前边添加一个关键字volatile:

package multiThread.volatilePack;

public class MyThread extends Thread {
	volatile boolean b = true;

	public boolean isRunning() {
		return b;
	}

	public void setRunning(boolean b) {
		this.b = b;
	}

	public void run() {

		System.out.println("进入了running了");
		System.out.println(b + "   这个是进入循环前的b----------");
		while (b == true) {

			// System.out.println("进入循环");
		}

		System.out.println("线程被停止了");
	}

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
		try {
			Thread.sleep(10);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		myThread.setRunning(false);

		System.out.println("已经设置为false了");

	}

}

控制台:

b.再看几个现象,关于jvm的两种运行模式

client和server,64位只有server模式,client是无效的。参考下边链接,我们上边的就是在64位server下测试的。如果是32的client就不一样了。

https://blog.csdn.net/Erica_1230/article/details/69934787

c.在while循环中,加入了打印语句的时候,上边的测试代码第一个情况就会不一样,有了打印语句后,我们当前线程也会跳转到公共值栈中取值,所以也会和公共值栈同步,所以会导致程序while中的b变为main中赋值的false

参考链接:https://blog.csdn.net/Ditto_zhou/article/details/83751386

下边的测试代码对第一个进行修改后:

package multiThread.volatilePack;

public class MyThread extends Thread {
	 boolean b = true;

	public boolean isRunning() {
		return b;
	}

	public void setRunning(boolean b) {
		this.b = b;
	}

	public void run() {

		System.out.println("进入了running了");
		System.out.println(b + "   这个是进入循环前的b----------");
		while (b == true) {

			System.out.print("进入循环");
		}

		System.out.println("线程被停止了");
	}

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
		try {
			Thread.sleep(10);
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		myThread.setRunning(false);

		System.out.println("已经设置为false了");

	}

}

控制台:

d.在main函数中是否添加sleep可能会导致效果不一样,有可能会改变进入while循环前b的值。因为最开始默认的b是true,但是在main线程中,修改为了false,但是进入while循环的时候,b到底是true还是false呢?这个就看执行时间 了

下边测试代码就是去掉主函数中的sleep函数,这个时候,我们main函数中的myThread.setRunning(false);就在while前先把b的值给改变了

package multiThread.volatilePack;

public class MyThread extends Thread {
	 boolean b = true;

	public boolean isRunning() {
		return b;
	}

	public void setRunning(boolean b) {
		this.b = b;
	}

	public void run() {

		System.out.println("进入了running了");
		System.out.println(b + "   这个是进入循环前的b----------");
		while (b == true) {

			System.out.print("进入循环");
		}

		System.out.println("线程被停止了");
	}

	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
//		try {
//			Thread.sleep(10);
//		} catch (InterruptedException e1) {
//			// TODO Auto-generated catch block
//			e1.printStackTrace();
//		}
		myThread.setRunning(false);

		System.out.println("已经设置为false了");

	}

}

控制台:

这里看到进入while的时候,b已经被修改为了false了

猜你喜欢

转载自blog.csdn.net/Handsome2013/article/details/85113126