Single Threaded Execution 模式

所谓Single Threaded Execution 模式,意思是“以一个线程执行”。就像独木桥同一时间只允许一个人通行一样,该模式用于 设置限制,以确保同一时间只能让一个线程执行处理。

不安全的代码:

非安全的Gate:

/**
 * 大门
 * @author Administrator
 *
 */
public class Gate {
         private int counter = 0;//表示目前为止已经通过这道门的人数
	private String name = "NoBody";//表示通行者的姓名
	private String address = "NoWhere";//表示该人的出生地

         /**
           * 表示的是通过门,该方法将表示通过人数的counter字段的值递增1,并将参数中传入的通行者的姓名和出生地
         **/
    public void pass(String name, String address) {
		this.counter++;
		this.name = name;
		this.address = address;
		check();
	}

	private void check() {
		//如果name与address首字母不同,那么说明记录数据是异常的
		if (name.charAt(0) != address.charAt(0)) {
			System.out.println("****** BROEKN ******" + toString());
		}

	}

	public String toString() {
		return "No." + counter + ":" + name + "," + address;
	}

}

UserThread类:不断通过门的人

/**
 * 用户线程
 * @author Administrator
 *
 */
public class UserThread extends Thread {
	private final Gate gate;
	private final String myname;
	private final String myaddress;

	public UserThread(Gate gate, String myname, String myaddress) {
		super();
		this.gate = gate;
		this.myname = myname;
		this.myaddress = myaddress;
	}

	@Override
	public void run() {
		System.out.println(myname + " BEGIN");
		//不断循环,并在循环中反复调用pass方法来表示这个人在门里不断的穿梭过去
		for (;;) {
			gate.pass(myname, myaddress);
		}
	}

}

测试类:Main

public class Main {
    public static void main(String[] args) {
        Gate gate = new Gate();
        new UserThread(gate, "Alice", "Alaska").start();
        new UserThread(gate, "Bobby", "Brazil").start();
        new UserThread(gate, "Chris", "Canada").start();
    }
}

运行结果:

Single Threaded Execution 模式_第1张图片

当Gate类的实例被多个线程使用时,运行结果与预期不一致,也就是说,这个Gate类是不安全的,是非线程安全的。


为什么会出错:

情形1:线程Alice和线程Bobby执行pass的:

线程Alice 线程Bobby this.name的值 this.address的值
this.counter++ this.counter++ 之前的值 之前的值
  this.name=name “Bobby” 之前的值
this.name = name   Alice 之前的值
this.address= address  
Alaska this.address=addressAliceBrazilcheck()check()AliceBrazil  ***** BROKEN ***** 

情形2:线程Alice和线程Bobby执行pass的:

线程Alice 线程Bobby this.name的值 this.address的值
this.counter++ this.counter++ 之前的值 之前的值
this.name=name   Alice 之前的值
  this.name=name Bobby 之前的值
  this.address=address Bobby Brazil
this.address=address   Bobby Alaska
check(); check(); Bobby Alaska
    ***** BROKEN *****  
       
       
       

线程安全带的Gate:

public class Gate {
	private int counter = 0;
	private String name = "NoBody";
	private String address = "NoWhere";

	public synchronized void pass(String name, String address) {
		this.counter++;
		this.name = name;
		this.address = address;
		check();
	}

	private void check() {
		// 当某个人的name首字母和地址的首字母一样的时候,打印语句
		if (name.charAt(0) != address.charAt(0)) {
			System.out.println("****** BROEKN ******" + toString());
		}

	}

	public synchronized String toString() {
		return "No." + counter + ":" + name + "," + address;
	}

}

Single Threaded Execution 模式_第2张图片


线程Alice和线程Bobby执行synchronized修饰的pass方法的情形:

线程Alice 线程Bobby this.name的值 this.address的值
[获取锁]      
this.counter++   之前的值 之前的值
this.name=name   Alice 之前的值
this.adderss=address   Alice Alaska
check()   Alice Alaska
[释放锁]      
  [获取锁]    
  this.counter++ Alice Alaska
  this.name=name Bobby Alaska
  this.adderess=address Bobby Brazil
  check(); Bobby Brazil
  [释放锁]    


关于synchronized

不管是synchronized 方法还是synchronized代码块,

synchronized 方法

 synchronized void method(){

    ...........

}

 synchronized (obj){

    ...........

}


无论哪种,都可以看作在"{"处获取锁,在"}"处释放锁。

显示处理锁的方法:

void method(){

   lock();

   .........

    unlock()

}

存在return时,锁无法被释放:

void method{
 lock();
 if(条件表达式){
    return;//此处如果执行return,unlock()就不会被调用
 }
 unlock();
}

doMethod抛出异常时,锁无法被释放:

void method(){
  lock();
  doMethod();//如果该方法只用抛出异常,unlock()就不会被调用
  unlock();
}

相对地,synchronized方法和synchronized代码块无论是执行return还是抛出异常,都一定能够释放锁。

调用lock()方法之后,无论执行什么操作,都会调用unlock方法;

void method(){
  lock();
	 try{
	 
	 }finally{
	  unlock();
	 }
	 
}
上述代码无论是return、抛出异常还是其他任何操作,finally部分都会被调用到。


你可能感兴趣的:(java多线程)