它是“一个线程”的意思,就像一个桥,每次只能通过一个人。
下面测试: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方法的时候要获取对象的锁定是需要时间的,当线程发生冲突的时候线程必须等待,这耗掉了很多时间。
相关推荐
1、Single Threaded Execution ———— 能通过这座桥的,只有一个人 2、Immutable ———— 想破坏它也没办法 3、Guarded Suspension ———— 要等到我们准本好哦 4、Balking ———— 不需要的话,就算了吧 5、...
第1章 Single Threaded Execution——能通过这座桥的,只有一个人 第2章 Immutable——想破坏它也没办法 第3章 Guarded Suspension——要等到我准备好喔 第4章 Balking——不需要的话,就算了吧 第5章 Producer-...
多线程入门,多线程基础知识,描述了Synchronized的线程互斥原理,和Single Threaded Execution模式,符合基础入门的用户可以好好学习,加深理解
第1章 Single Threaded Execution——能通过这座桥的,只有一个人 第2章 Immutable——想破坏它也没办法 第3章 Guarded Suspension——要等到我准备好喔 第4章 Balking——不需要的话,就算了吧 第5章 Producer-...
- **单线程执行(Single Threaded Execution)** - **定义**: 确保在单一的线程中执行特定的操作。 - **应用场景**: 当需要确保特定操作不会被并发执行时。 - **缓存管理(Cache Management)** - **定义**: 一种用于...
### 基本设计模型(Fundamental Design Patterns) #### 1.1 授权(Delegation)(When not to use inheritance) **特点:** 在面向对象编程中,继承是一种常用的设计方式,但有时它并不是最合适的解决方案。...
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....
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-...
- **Single-Threaded Deadlocks:** Even single-threaded applications can experience deadlocks if synchronized blocks are used incorrectly, such as nesting synchronized blocks improperly. - **Thread....
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...
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 ...
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 ...
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 ...
Delphi 7.1 Update Release Notes=======================================================This file contains important supplemental and late-breakinginformation that may not appear in the main ...