知识大全 多线程编程的设计模式 临界区模式
Posted 知
篇首语:不经过琢磨,宝石也不会发光。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 多线程编程的设计模式 临界区模式相关的知识,希望对你有一定的参考价值。
临界区模式 Critical Section Pattern 是指在一个共享范围中只让一个线程执行的模式 它是所有其它多线程设计模式的基础 所以我首先来介绍它 把着眼点放在范围上 这个模式叫临界区模式 如果把作眼点放在执行的线程上 这个模式就叫单线程执行模式
首先我们来玩一个钻山洞的游戏 我 Axman 朋友 Sager 同事 Pentium 三个人在八角游乐场循环钻山洞(KAO 减肥训练啊) 每个人手里有一个牌子 每钻一次洞口的老头会把当前的次序 姓名 牌号显示出来 并检查名字与牌号是否一致
OK 这个游戏的参与者有游乐场老头Geezer Player 就是我们 还有山洞 corrie
public class Geezer public static void main(String[] args) System out println( 预备 开始! ); Corrie c = new Corrie();//只有一个山洞 所以生存一个实例后传给多个Player new Player( Axman c) start(); new Player( Sager c) start(); new Player( Pentium c) start();
这个类暂时没有什么多说的 它是一个Main的角色
public class Player extends Thread private final String name; private final String number; private final Corrie corrie; public Player(String name String number Corrie corrie) this name = name; this number = number; rrie = corrie; public void run() while(true) rrie into(this name this number); 在这里 我们把成员字段都设成final的 为了说明一个Player一旦构造 他的名字和牌号就不能改变 简单说在游戏中 我 Sager Pentium 三个人不会自己偷偷把自己的牌号换了 也不会偷偷地去钻别的山洞 如果这个游戏一旦发生错误 那么错误不在我们玩家
import java util *;public class Corrie private int count = ; private String name; private String number; private HashMap lib = new HashMap();//保存姓名与牌号的库 public Corrie() lib put( Axman ); lib put( Sager ); lib put( Pentium ); public void into(String name String number) unt ++; this name = name; this number = number; if(this lib get(name) equals(number)) test(): public String display() return unt+ : + this name + ( + this number + ) ;
private void test() if(this lib get(name) equals(number)) ; //System out println( OK: + display()); else System out println( ERR: + display());
这个类中增加了一个lib的HashMap 相当于一个玩家姓名与牌号的库 因为明知道Corrie只有一个实例 所以我用了成员对象而不是静态实例 只是为了能在构造方法中初始化库中的内容 从真正意义中说应该在一个辅助类中实现这样的数据结构封装的功能 如果不提供这个lib 那么在check的时候就要用if(name equasl( Axman )) if(!number equals( )) //出错else if 这样复杂的语句 如果player大多可能会写到手抽筋 所以用一个lib来chcek就非常容象
运行这个程序需要有一些耐心 因为即使你的程序写得再差在很多单线程测试环境下也能可是正确的 而且多线程程序在不同的机器上表现不同 要发现这个例子的错识 可能要运行很长一段时间 如果你的机器是多CPU的 那么出现错误的机会就大好多
在我的笔记本上最终出现错误是在 分钟以后 出现的错误有几钟情况: : ERR:Axman( ) : ERR:Sager( )第一种情况是检查到了错误 我的牌号明明是 却打印出来 而第二种明明没有错误 却打印了错误
事实上根据以前介绍的多线程知识 不难理解这个例子的错误出现 因为into不是线程安全的 所以在其中一个线程执行this name = Axman ;后 本来应该执行this numner= 却被切换到另一个线程中执行this number= 然后又经过不可预知的切换执行其中一个的if(this lib get(name) equals(number))而出现 的错误 而在打印这个错误时因为display也不是线程安全的 正要打印一个错误的结果时 由于this name或this number其中一个字段被修改却成了正确的匹配而出现错误
另外还有可能会出现序号颠倒或不对应 但这个错误我们无法直观地观察 因为你根本不知道哪个序号 应该 给哪个Player 而序号颠倒则有可能被滚动的屏幕所掩盖
[正确的Critical Section模式的例子]我们知道出现这些错误是因为Corrie类的方法不是线程安全的 那么只要修改Corrie类为线程安全的类就行了 其它类则不需要修改 上面说过 如果出现错误那一定不是我们玩家的事:
import java util *;public class Corrie private int count = ; private String name; private String number; private HashMap lib = new HashMap();//保存姓名与牌号的库 public Corrie() lib put( Axman ); lib put( Sager ); lib put( Pentium ); public synchronized void into(String name String number) unt ++; this name = name; this number = number; test(); public synchronized String display() return unt+ : + this name + ( + this number + ) ;
private void test() if(this lib get(name) equals(number)) ; //System out println( OK: + display()); else System out println( ERR: + display());
运行这个例子 如果你的耐心 开着你的机器运行三天吧 虽然测试 天并不能说明第 天没有出错 at least 现在的正确性比原来那个没有synchronized 保护的例子要可靠多了!
cha138/Article/program/Java/gj/201311/27591相关参考
Java自带的Future多线程模式 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &n
/*@authorshijin*生产者与消费者模型中要保证以下几点*同一时间内只能有一个生产者生产 生产方法加锁sychronized*同一时间内只能
Java多线程编程基础之线程和多线程 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 随着计算机技
超线程多核心下Java多线程编程分析 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一Java环
超线程多核心下Java多线程编程技术分析[4] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
超线程多核心下Java多线程编程技术分析[3] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
超线程多核心下Java多线程编程技术分析[1] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
超线程多核心下Java多线程编程技术分析[2] 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!&nb
Java多线程编程基础之线程对象 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! &nbs
在计算机编程中一个基本的概念就是同时对多个任务加以控制许多程序设计问题都要求程序能够停下手头的工作改为处理其他一些问题再返回主进程可以通过多种途径达到这个目的最开始的时候那些拥有机器低级知识的程序