`

Single Threaded Execution

 
阅读更多

它是“一个线程”的意思,就像一个桥,每次只能通过一个人。

下面测试:Gate是表示门的类,经过门(pass)会检查姓名与address的首字母是否相同,如果不同,输出
                  Passer继承了Thread,它一直反复通过门
                  Main中有三个Passer,让这三个Passer通过同一个门(这里意味着gate的信息是共享的)

public class Gate {
	private int counter=0;
	private String name="Nobody";
	private String address="Nowhere";
	
	public void pass(String name,String address){
		this.counter++;
		this.name=name;
		this.address=address;
		check();
	}
	private void check(){
		if(name.charAt(0)!=address.charAt(0))
			System.out.println("*****BROKEN*****"+toString());
	}
	
	@Override
	public String toString(){
		return "No."+counter+":"+name+","+address;
	}
}
public class Passer extends Thread{
	private final Gate gate;
	private final String myname;
	private final String myaddress;
	
	public Passer(Gate gate,String myname,String myaddress){
		this.gate=gate;
		this.myname=myname;
		this.myaddress=myaddress;
	}
	
	@Override
	public void run(){
		System.out.println(myname+" BEGIN");
		while(true){
			gate.pass(myname, myaddress);
		}
	}
}

 

public class Main {
	public static void main(String[] args){
		System.out.println("hit Ctrl+C to exit");
		Gate gate=new Gate();
		//三个Passer用了同一个gate
		new Passer(gate,"Alice","Alaska").start();
		new Passer(gate,"Bobby","Brazil").start();
		new Passer(gate,"Chris","Canada").start();
	}
}

 运行结果:

hit Ctrl+C to exit
Alice BEGIN
Bobby BEGIN
*****BROKEN*****No.878:Bobby,Brazil
*****BROKEN*****No.1387:Bobby,Brazil
*****BROKEN*****No.23170:Alice,Alaska
*****BROKEN*****No.28157:Bobby,Brazil
*****BROKEN*****No.54236:Alice,Alaska
*****BROKEN*****No.59996:Bobby,Brazil
*****BROKEN*****No.69240:Bobby,Brazil
*****BROKEN*****No.77988:Alice,Alaska
*****BROKEN*****No.83399:Bobby,Brazil
*****BROKEN*****No.91945:Alice,Alaska
*****BROKEN*****No.97449:Bobby,Brazil
*****BROKEN*****No.106786:Alice,Alaska
*****BROKEN*****No.140881:Bobby,Brazil
*****BROKEN*****No.149914:Alice,Alaska
*****BROKEN*****No.183557:Alice,Alaska
*****BROKEN*****No.188912:Bobby,Brazil
*****BROKEN*****No.198266:Bobby,Brazil
*****BROKEN*****No.206391:Alice,Alaska
*****BROKEN*****No.237655:Bobby,Brazil
*****BROKEN*****No.245603:Bobby,Brazil
*****BROKEN*****No.561550:Alice,Brazil
*****BROKEN*****No.561550:Alice,Brazil

。。。。。(这时第三个线程还没有运行,其实这三个线程的运行顺序是不可知的)

 

原因分析:这个线程在check时,另外一个线程改变了gate的属性值。

应该做如下修改来保证每个时刻只有一个Passer进入gate的pass方法:

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(){
		if(name.charAt(0)!=address.charAt(0))
			System.out.println("*****BROKEN*****"+toString());
	}
	
	@Override
	public synchronized String toString(){
		return "No."+counter+":"+name+","+address;
	}
}

 这里check()是不需要用synchronized,因为check是private的,且只有pass才会调用它,而pass已经设置为synchronized的了。而String是public的,如果它不设置为synchronized,那么如果有线程调用toString的同时,另外一个Passer线程正修改完name而准备修改address,那么这样造成显示不一致了。

 

        当多个线程共享同一个实例时候,多个线程独自改变实例的状态,使得实例丧失安全性。首先,需要找到不稳定的范围(临界区间),对临界区间进行保护,使同时执行的线程保持只有一条,这也就是Single Threaded Execution Pattern。当数据被多个线程访问、状态可能改变、需要确保安全时就可以使用这种模式。        java里可以用synchronized来实现临界区间。
synchronized void method(){....}

synchronized (obj){......}

void method(){
    lock();
    ....       //这里如果有return 或者异常,那么锁就没有解开
    unlock();
}

void method(){
    lock();
    try{
       ....    
    }
    finally{
        unlock();
    }
}
         这个模式会使程序的执行性能降低,因为在进入synchronized方法的时候要获取对象的锁定是需要时间的,当线程发生冲突的时候线程必须等待,这耗掉了很多时间。 
       从多线程的角度来讲,synchronized方法是具有原子性的,当它执行时是不允许其他线程进入这个方法的。在java规格中,char、int、对象引用类型等是具有原子性的,而long、double就不具有原子性了。如果一个线程执行longField=123L,而同时另外一个线程执行longField=456L,这样操作后,longField里面的值是无法保证的,甚至可能既不是123L也不是456L。在声明字段的时候加上volatile关键字,那么所有对该字段的操作就变得不可分割。因此,线程共享long或者double的字段的时候,必须在synchronized中操作或者声明加上volatile。
        这个模式使用时可能存在死锁的情况。例如Ally和Bob用同一套spoon和fork进餐时,当每个人各自那一样餐具时就出现了死锁。
package deadlock;

public class DeadLockTest {
	public static void main(String[] args){
		Tool spoon=new Tool("spoon");
		Tool fork=new Tool("fork");
		new EaterThread("Alice",spoon,fork).start();
		new EaterThread("Bob",fork,spoon).start();
	}
}
 
package deadlock;

public class Tool {
	private String toolname;
	public Tool(String name){
		toolname=name;
		}
	@Override
	public String toString(){
		return "["+toolname+"]";
	}
}
 
package deadlock;

public class EaterThread extends Thread{
	private String person;
	private final Tool leftTool;//左手拿的工具
	private final Tool rightTool;//右手拿的工具
	public  EaterThread(String person,Tool leftTool,Tool rightTool){
		this.person=person;
		this.leftTool=leftTool;
		this.rightTool=rightTool;
	}
    @Override
    public void run(){
    	while (true){
    		eat();
    	}
    }
	private void eat() {
		synchronized(leftTool){    //使用左手的工具,这个工具不许其他人使用
			System.out.println(person+" use"+leftTool+"L");
			synchronized(rightTool){//使用右手的工具,这个工具不许其他人使用
				System.out.println(person+" use"+rightTool+"R");
				System.out.println(person+" begin to eat!_1_2_3 finish eating!");
				System.out.println(person+" putdown "+rightTool);
			}
			System.out.println(person+" putdown "+leftTool);
			System.out.println("finish!");
		}
	}
}
 运行结果:
Alice use[spoon]L
Alice use[fork]R
Alice begin to eat!_1_2_3 finish eating!
Alice putdown [fork]
Alice putdown [spoon]
finish!
Alice use[spoon]L
Bob use[fork]L

这样一直出现等待。。。。。。

分享到:
评论

相关推荐

    Java多线程详解

    1、Single Threaded Execution ———— 能通过这座桥的,只有一个人 2、Immutable ———— 想破坏它也没办法 3、Guarded Suspension ———— 要等到我们准本好哦 4、Balking ———— 不需要的话,就算了吧 5、...

    java多线程设计模式 (PDF中文版, 附源码)

    第1章 Single Threaded Execution——能通过这座桥的,只有一个人 第2章 Immutable——想破坏它也没办法 第3章 Guarded Suspension——要等到我准备好喔 第4章 Balking——不需要的话,就算了吧 第5章 Producer-...

    多线程.txt

    多线程入门,多线程基础知识,描述了Synchronized的线程互斥原理,和Single Threaded Execution模式,符合基础入门的用户可以好好学习,加深理解

    java多线程设计模式详解(PDF及源码)

    第1章 Single Threaded Execution——能通过这座桥的,只有一个人 第2章 Immutable——想破坏它也没办法 第3章 Guarded Suspension——要等到我准备好喔 第4章 Balking——不需要的话,就算了吧 第5章 Producer-...

    Design Pattern Quick Reference Card

    - **单线程执行(Single Threaded Execution)** - **定义**: 确保在单一的线程中执行特定的操作。 - **应用场景**: 当需要确保特定操作不会被并发执行时。 - **缓存管理(Cache Management)** - **定义**: 一种用于...

    Pattens In Java.pdf

    ### 基本设计模型(Fundamental Design Patterns) #### 1.1 授权(Delegation)(When not to use inheritance) **特点:** 在面向对象编程中,继承是一种常用的设计方式,但有时它并不是最合适的解决方案。...

    Semantics of Asynchronous JavaScript

    Since the JavaScript language is single threaded, Node.js programs must make use of asynchronous callbacks and event loops managed by the runtime to ensure appli- cations remain responsive....

    国产纯Java多核体系结构模拟器Archimulator.zip

    Single-threaded superscalar out-of-order execution, multithreaded SMT and CMP execution model; Multi-level inclusive cache hierarchy with the directory-based MESI coherence protocol; Simple cycle-...

    SCJP 6 question demo

    - **Single-Threaded Deadlocks:** Even single-threaded applications can experience deadlocks if synchronized blocks are used incorrectly, such as nesting synchronized blocks improperly. - **Thread....

    Tegra2_sec

    The MPCore (Multi-Processor Core) variant allows for multi-threaded execution and parallel processing, which significantly improves overall system performance. #### Key Features of the ARM Cortex-A9...

    [Mastering.Node.js(2013.11) 精通Node.js

    The benefits of single-threaded programming 186 Multithreading is already native and transparent 189 Creating child processes 190Table of Contents [ v ] Spawning processes 192 Forking processes 195 ...

    acpi控制笔记本风扇转速

    threaded. The overhead of a semaphore per-method is eliminated. Fixed a regression where an error was no longer emitted if a control method attempts to create 2 objects of the same name. This once ...

    i-vector的工具箱

    Single-threaded executables are useful when running the tools on clusters that only allow a single CPU process per scheduled job. To generate multithreaded executables (this is important when using ...

    Delphi7.1 Update

    Delphi 7.1 Update Release Notes=======================================================This file contains important supplemental and late-breakinginformation that may not appear in the main ...

Global site tag (gtag.js) - Google Analytics