多线程之竞态

准备知识点:

1.竞态:指多线程情况下计算的正确性依赖于相对时间顺序或线程的交错;

2.状态变量:类的实例变量、静态变量;

3.共享变量:能够被多个线程共同访问的变量,状态变量也属于共享变量;

4.竞态产生模式:有两种

    a) 读-改-写

    b) 检查-行动

    在下面的程序中直接演示了这两种情况

5.局部变量的使用不会产生竞态;

6.原子性:意思是不可分割,就好比去饮料机买饮料,我只负责选择然后取货,选择->取货这期间的处理是我们看不到的,相当于一盒黑盒,我们无法去左右它,这个黑盒我们称为原子性;

7.下面的程序中

静态变量mark 的 ++ 操作代码上看似一步其实jvm中解析出的指令分为了三步,也就是竞态模式的 读-改-写

1) load--将mark的值从内存中读取到寄存器r1里

2) increment--寄存器值+1

3) store--将寄存器里的内容写入mark的内存空间

getId()方法中的if-else条件则是竞态模式中的检查-行动

package test

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 模拟多线程中竞态的产生
 *
 */
public class RaceCondition {
	
	public static void main(String[] args) {
		Client[] cl = new Client[100];
		//先准备好待会一起发送
		for (int i = 0; i < 100; i++) {
			Client client = new Client(String.valueOf(i));
			cl[i] = client;
		}
		//发送
		for (int i = 0; i < cl.length; i++) {
			cl[i].start();;
		}
	}
	
}

/**
 * 模拟web中给每个请求发放一个唯一的id标记 
 * 前缀4000+年月日时分秒毫秒+后缀000-999
 */
class RequestUtil{
	
	//这个属于状态变量(类的实例变量,静态变量都属于状态变量)
	private static final RequestUtil REQUEST_UTIL = new RequestUtil();
	private static final int MAX = 999;
	//这个属于状态变量(类的实例变量,静态变量都属于状态变量),能够被多个线程共同访问的变量也叫共享变量
	private static int mark = -1;
	private static final SimpleDateFormat FORMAT= new SimpleDateFormat("yyyyMMddHHmmsssss"); 
	//私有化构造方法
	private RequestUtil(){}
	
	public static RequestUtil getInstance(){
		return REQUEST_UTIL;
	}
	
	public static String getReqId(){
		if(mark > MAX){
			mark = 0;
		}else{
			mark++;
		}
		return "4000" + FORMAT.format(new Date()) + new DecimalFormat("000").format(mark);
	}
}

/**
 * 模拟客户端请求
 *
 */
class Client extends Thread{
	private String name;
	
	public Client(String name) {
		this.name = name;
	}

	@SuppressWarnings("static-access")
	@Override
	public void run() {
		String reqId = RequestUtil.getInstance().getReqId();
		System.out.println("线程"+name+":获取请求id["+reqId+"]");
	}
}


因为出现了竞态产生的条件,结果可以看出不同线程可能获取到了相同的id。

解决这个竞态比较简单的方法就是让getId()方法变成原子性,可使用关键字 synchronized ,public static synchronized String getReqId()

mark 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值