zoukankan      html  css  js  c++  java
  • Single Thread Execution 能通过这座桥的只有一个人

    直奔主题, Single Thread Execution也称作Critical Section(临界区),范例如下:

    public class SingleThreadGate {
    	public static void main(String[] args) {
    		System.out.println("ctrl + c to exit.");
    		
    		Gate gate = new Gate();
    		new UserThread(gate, "Alice", "Alaska").start();
    		new UserThread(gate, "Bobby", "Brazil").start();
    		new UserThread(gate, "Chris", "Canada").start();
    	}
    }
    
    class Gate{
    	private int count;
    	private String name;
    	private String address;
    	
    	public void pass(String name, String address){
    		this.count++;
    		this.name=name;
    		this.address=address;
    		
    		check();
    	}
    	
    	public void check() {
    		if (name.charAt(0) != address.charAt(0)) {
    			System.out.println("*******BROKEN *******" + toString());
    		}
    	}
    
    	@Override
    	public String toString() {
    		return "No." + count + " " + name + ", " + address;
    	}
    	
    }
    
    class UserThread extends Thread{
    	private Gate gate;
    	private String name;
    	private String address;
    	
    	public UserThread(Gate gate, String name, String address){
    		this.gate=gate;
    		this.name=name;
    		this.address=address;
    	}
    
    	@Override
    	public void run() {
    		System.out.println(name+":begin->");
    		while(true){
    			gate.pass(name,address);
    			Thread.yield();
    		}
    	}
    }
    

    执行之后,会发现ou一很多broken,因为在执行pass的时候成员变量被其他线程改变了,所以判断name和address不一致,另外toString方法也存在同样的问题,执行过程中 name和address也随时被其他线程改变,所以会导致同一条记录的name和address也不一致,结果如下:

    ctrl + c to exit.
    Alice:begin->
    Chris:begin->
    Bobby:begin->
    *******BROKEN *******No.306 Bobby, Brazil
    *******BROKEN *******No.487 Chris, Canada
    *******BROKEN *******No.624 Bobby, Brazil
    *******BROKEN *******No.6956 Bobby, Brazil
    *******BROKEN *******No.7487 Alice, Canada
    *******BROKEN *******No.7756 Chris, Alaska
    *******BROKEN *******No.8010 Alice, Canada
    *******BROKEN *******No.8288 Bobby, Brazil
    *******BROKEN *******No.8550 Chris, Alaska
    *******BROKEN *******No.8910 Bobby, Brazil
    *******BROKEN *******No.9397 Chris, Alaska
    *******BROKEN *******No.9715 Bobby, Brazil

    那么如何改进呢?将pass方法加上synchronized关键字,这样就不会有任何错误了。不过这还不能保证整个gate类的所有方法都是安全的,当调用toString方法时还是会有同样的name与address不一致的问题,所以在toString方法上也要加上synchronized关键字,那么check方法还需要么?答案是不需要,因为check方法时私有的,外部无法访问,而且check方法是被pass方法调用的,而pass方法已经同步了,一个类中的synchronized关键之都是锁定的同一对象(this),所以不需要二次锁定,浪费性能。

     synchnronized关键字也可以理解成把方法变成原子性操作,在java中,基本数据类型(primitive)如int, char, byte等都是原子性操作的,但是long和double则不一定,所以我们想把long和double这类非原子性类型按照原子性方式操作,需要加上关键字volatile,这样就可以了。

  • 相关阅读:
    十三种基于直方图的图像全局二值化算法原理、实现、代码及效果。
    基于模糊集理论的一种图像二值化算法的原理、实现效果及代码
    双指数边缘平滑滤波器用于磨皮算法的尝试。
    《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)
    肤色检测算法
    肤色检测算法
    基于Simple Image Statistics(简单图像统计,SIS)的图像二值化算法。
    图像偏色检测算法,速度快,效果好,共享给大家。
    .net下灰度模式图像在创建Graphics时出现:无法从带有索引像素格式的图像创建graphics对象 问题的解决方案。
    一个简单的统计图像主颜色的算法(C#源代码)
  • 原文地址:https://www.cnblogs.com/gaotianle/p/3307444.html
Copyright © 2011-2022 走看看