并发之volatile标记位为何不适合于停止线程且与interrupt中止线程原理

volatile标记位为何不适合于停止线程且与interrupt中止线程原理

Volatile解释

  • volatile 是一个类型修饰符,作为一个指令关键字使用。如: public volatile boolean is_stop = false; volatile 保证修饰数据可见性,即所有对加的这个修饰词的变量的更新操作都能够被其他线程所看到。
  • 从内存的角度来看,volatile在多处理器下,实现了缓存一致性协议,即保证各个处理器的缓存是一致的。具体实现是:

    每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。

Volatile标记位实现停止线程

借用volatile的缓存一致性,将volatile修饰的数据看成flag来实现停止线程,如下的is_stop:

class test extends Thread{
	public volatile boolean is_stop = false;
	StorageDemo storage = new StorageDemo();
	public void run() {

		while(!is_stop) {
			storage.put(50); //如果这里阻塞/休眠/等待会怎么杨
			System.out.println(storage.getNum());
		}

		
	}
}

Storage类

class StorageDemo{
	int num=0;
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public void put(int addNum) {
			//200为库满
			if(num<200) {
				num+=addNum;
				System.out.println(addNum);
			}

	}
}

主函数

test t = new test();
t.start();
Thread.sleep(1000);
t.is_stop=true;
System.out.println("has been done");

结果显示在这里插入图片描述
这样通过volatile实现了,终止线程的操作。但是值得注意的是volatile只适合** 一 定 条 件 下 \color{red}{一定条件下} **的终止线程。

非一定条件下的volatile标记位

当循环中的语句陷入阻塞/休眠/等待,比如:storage.put(50);将会怎么样?volatile关键字还会起作用吗?

//将storage的put方法中休眠很长一段时间
if(num<200) {
				num+=addNum;
				System.out.println(addNum);
			}
			try {
				Thread.sleep(4000000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
  • 答案是不会
  • 其效果为如下:注意到先右边线程并未停止。在这里插入图片描述
    为什么不会其作用呢?关键在于run方法中:
while(!is_stop) {
			storage.put(50); // 就在这里被put方法被阻塞一直睡眠/阻塞/等待
			System.out.println(storage.getNum());
		}

只有当put方法执行完,volatile修饰的is_stop才会起作用将线程终止。但是如果陷入死锁,或其它等待时间过长,那将不会终止,直至put方法执行完毕。这样如果被阻塞时间很长,明显是不合适的。这时针对这种情况就需要interrupt了。

Interrupt中止线程原理

  • interrupt(中断)是在线程对象做一个标记而已,称为中断标志。这个标记平常线程并不会去检测,( 前 提 \color{red}{前提} )只有当线程陷入wait、join、yield、sleep这些阻塞情况的时候才会去不断检查中断标记,然后去中止线程。
  • 但是值得注意的是中止与终止二者含义并不相同,中止是:这些被阻塞的线程检查到自己的中断标志为true,就会抛出InterruptException异常,进行捕获处理,从而达到中止的目的。效果如下:
  • 注意到线程并未中终止,仅仅只是中止。在这里插入图片描述
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长臂人猿

客官们众筹请博主喝杯奶茶吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值