Single Threaded Execution Pattern
来源:互联网 发布:js获取自定义属性data 编辑:程序博客网 时间:2024/05/17 01:51
什么是Single Threaded Execution Pattern?
想象一个情景,一群人想要过一座桥,但是这个桥只能容忍一个人的质量,当一个人以上经过这座桥,这座桥就会断裂,我们先使用线程不安全的代码来实现这一过桥情景。
首先写桥类:
package singleThreadedExecution;public class Gate { private int count = 0;//计数已经过桥的人 private String name;//正在桥上的人名 private String nameBackUp;//人名备份 如果和桥上人不一致说明桥上不止一个人 public void pass(String name){//过桥 this.name = name; this.nameBackUp = name;//做一个备份 this.count++; } @Override public String toString(){ return "name:"+this.name+" nameBackUp:"+this.nameBackUp; } public void check(){//检测桥断没断 if(this.name != this.nameBackUp){ System.out.println("Oops! The gate is broken! There are "+this.count+"men has passed this gate."); } }}然后写实现了Runnable接口的类:
package singleThreadedExecution;public class UsingThread implements Runnable { private Gate gate; private String name; public UsingThread(Gate gate , String name){ this.gate = gate; this.name = name; } @Override public void run() { while(true){ gate.pass(name);//name这个人过桥 gate.check();//检测 } }}最后做一个测试:
package singleThreadedExecution;public class Test { public static void main(String[] args) { Gate gate = new Gate(); UsingThread t1 = new UsingThread(gate, "Cherry"); UsingThread t2 = new UsingThread(gate, "Tommy"); UsingThread t3 = new UsingThread(gate, "Diana"); new Thread(t1).start(); new Thread(t2).start(); new Thread(t3).start(); }}运行结果如下:
果然桥断了,为什么会这样呢?
因为在执行pass()方法和check()方法的时候,这两个方法内部的语句可能时交错执行的(这样说时把语句当成线程的基本操作单位,事实上线程可能以更小的单位在切换),而交错执行就导致了预料之外的情况。
我们看,第一次桥短的时候已经有3146个人通过了,这说明当运行次数少的时候我们可能根本无法发现这个问题。
怎么解决这个问题呢?
我们只需要在check()和pass()方法加上synchronized关键字进行修饰就行。因为这个关键字保证了只有一个线程(一个想过桥的人)能进行check()和pass(),而在这个阶段其他人想过桥都会被拦下。
这是一个很具体的例子,现在我们来抽象一下这个单线程模型:
首先介绍一个概念:sharedResource(共享资源)参与者,sharedResource参与者是可由多个线程访问的类,它的方法可以分为
1、safeMethod(安全的方法),不需要做特别处理
2、unsafeMethod(不安全的方法),被多个线程同时执行会产生预想不到的问题,必须加以防卫,使得多个线程不能同时访问这个方法。只能让单线程执行的程序范围叫做临界区(critical section)。
什么时候使用Single Threaded Execution?
1、多线程时,单线程程序显然不需要考虑这个问题。
2、数据可以被多个线程访问的时候。
3、状态可能变化的时候。
4、需要确保安全性的时候。
jdk提供的线程安全的包装方法
1、synchronizedCollection方法
2、synchronizedList方法
3、synchronizedMap方法
4、synchronizedSet方法
5、synchronizedSortedMap方法
6、synchronizedSortedSet方法
生命性与死锁
使用Single Threaded Execution pattern可能会发生死锁。
所谓死锁就是两个线程分别获得了锁,互相等待另一个锁释放锁,两个程序都无法继续,程序失去了生命性。
死锁的产生条件
1、具有多个sharedResource参与者。
2、线程锁定一个sharedResource时,还没接触钱就去锁定另一个sharedResource。
3、获取sharedResource参与者的顺序不固定(和sharedResource参与者对等,也就是没有固定的优先级)。
Single Threaded Execution使得程序执行性能减少的原因:
1、获取锁要花时间,可以减少sharedResource参与者的数量,以减少性能损失
2、线程冲突时没有锁的线程要进行等待,可以减少临界区范围,以减少出现线程冲突的机会。
原子性
所谓原子性就是不能再分的东西,Java语言规范中,一些基础类型的赋值和引用操作是原子的。对象等引用类型的赋值和引用操作也是原子的,因此即使不加上synchronized,也不会被分割。
比如现在有一个int型字段n,一个线程进行 n = 123; 另一个进行 n = 456;这样的操作导致n不是123就是456。
然而Java的long和double的指定、引用操作并不是不可分割的,对于一个线程进行l = 123L; 另一个进行l = 456L;这样的操作之后l会变成什么无法保证,也许是123L,也许是456L,也许是0L,甚至31415926L,当然现在大部分Java执行环境都将long和double当作原子操作来实现了。
对于想要保证这样的字段操作的原子性问题可以在synchronized方法内进行操作,还有一种方法就是声明变量的时候加上volatile关键字,使得对这个字段的操作变得不可分。
- Single Threaded Execution Pattern
- 线程之旅--Single Threaded Execution Pattern
- 多线程模式之-single Threaded Execution Pattern
- 多线程学习系列 - 1 - Single Threaded Execution Pattern
- 【Java学习笔记】17:Single Threaded Execution Pattern
- 第一章 Single Threaded Execution
- Multi-threaded design patterns -- Single Threaded Execution
- Java线程之Single Threaded Execution Pattern的思维导图
- java多线程设计模式——学习笔记(2)Single Threaded Execution Pattern
- Single Threaded Execution----java多线程设计模式(一)
- Java中的线程(八)- Single Threaded Execution模式
- 多线程设计模式(一) Single Threaded Execution
- [STAThread]即 single-threaded apartment
- Is javascript guaranteed to be single-threaded?
- Single Thread Execution
- Single Thread Execution
- Single Disign Pattern
- php-single pattern
- PatchMatch
- MyBatis的动态sql_set与if结合的动态更新
- 【java学习记】—勤快式、懒汉式单例
- 吐槽。
- MySQL常用操作
- Single Threaded Execution Pattern
- 简单理解操作系统中的PV操作
- JAVA学习笔记(一)类的多态
- 文件的基本操作总结
- HTML第二节点学习笔记
- 推荐系统(Recommender Systems)
- POJ-1155-TELE
- Objective-C (iOS)实现TCP反向代理(Port forward隧道)
- 创建设备节点问题