概念
single thread execution 即“以一个线程执行”。就像独木桥同一时间只允许一个人通行一样,该模式主要用于限制,以确保同一时间内只能让一个线程执行处理。
实现
主要使用synchronized关键字实现。
角色(使用的对象)
SharedResource(共享资源)
使用synchronized对方法或者代码块使用以保护共享资源
死锁
在该模式下发生死锁的条件:
- 存在多个ShareResource 角色
- 线程在持有某个ShareResource 角色锁的同时,还想获得其他ShareResource角色的锁
- 获取ShareResource角色的锁的顺序并不是固定的(ShareResource角色是对称的)
笔记
- 对于多线程来说,继承会引起一些麻烦的问题,通常称之为继承反常。
- 该模式会降低程序性能(1..获取锁会花费时间2线程冲突引起的等待)
- java编程规范定义了一些原子操作。eg:char,int等基本类型(primitive type)的赋值和引用操作都是原子的,对象等引用类型(reference type)的赋值和引用也是原子的。但是,也有例外,Java编程规范规定,long、double的复制和引用操作不是原子的。(实际上大部分Java虚拟机也都将long和double的操作实现为了原子)
- 对字段加上volatile关键字,对该字段的操作就是原子的了
延伸
java.util.concurrent包和计数信号量
资源的许可数将通过Semaphore的构造函数来指定
Semaphore的acquire用于确保有可用资源,release方法用于释放资源
package singleThreadExecution;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class BoundResource {
private final Semaphore semaphore;
private final int permits;
private final static Random random = new Random(314159);
public BoundResource(int permits) {
this.semaphore = new Semaphore(permits);
this.permits = permits;
}
public void use() throws InterruptedException {
semaphore.acquire(); //判断是否有资源可用,不可用等待
try {
doUse();
}finally {
semaphore.release(); //释放资源
}
}
/**
* 实际使用资源
* @throws InterruptedException
*/
protected void doUse() throws InterruptedException {
Log.println("BEGIN: used = " + (permits - semaphore.availablePermits()));
Thread.sleep(random.nextInt(500));
Log.println("END: used = " + (permits - semaphore.availablePermits()));
}
}
package singleThreadExecution;
public class Log {
public static void println(String s){
System.out.println(Thread.currentThread().getName() + ":" + s);
}
}
package singleThreadExecution;
public class Main {
public static void main(String[] args) {
BoundResource boundResource = new BoundResource(3);
for (int i=0;i<10;i++){
new UserThead(boundResource).start();
}
}
}
package singleThreadExecution;
import java.util.Random;
public class UserThead extends Thread {
private final static Random random = new Random(26535);
private final BoundResource boundResource;
public UserThead(BoundResource boundResource){
this.boundResource = boundResource;
}
@Override
public void run() {
while (true){
try {
boundResource.use();
Thread.sleep(random.nextInt(3000));
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
结果
Thread-0:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-2:BEGIN: used = 3
Thread-1:END: used = 3
Thread-3:BEGIN: used = 3
Thread-3:END: used = 3
Thread-4:BEGIN: used = 3
Thread-2:END: used = 3
Thread-5:BEGIN: used = 3
Thread-4:END: used = 3
Thread-6:BEGIN: used = 3
Thread-6:END: used = 3
Thread-7:BEGIN: used = 3
Thread-0:END: used = 3
Thread-8:BEGIN: used = 3
Thread-5:END: used = 3
Thread-9:BEGIN: used = 3
Thread-8:END: used = 3
Thread-9:END: used = 2
Thread-1:BEGIN: used = 2
Thread-7:END: used = 2
Thread-8:BEGIN: used = 2
Thread-3:BEGIN: used = 3
Thread-1:END: used = 3
Thread-4:BEGIN: used = 3
Thread-8:END: used = 3
Thread-3:END: used = 2
Thread-4:END: used = 1
Thread-7:BEGIN: used = 1
Thread-7:END: used = 1
Thread-4:BEGIN: used = 1
Thread-4:END: used = 1
Thread-5:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-1:END: used = 2
Thread-4:BEGIN: used = 2
Thread-5:END: used = 2
Thread-2:BEGIN: used = 2
Thread-9:BEGIN: used = 3
Thread-4:END: used = 3
Thread-0:BEGIN: used = 3
Thread-2:END: used = 3
Thread-0:END: used = 2
Thread-3:BEGIN: used = 2
Thread-8:BEGIN: used = 3
Thread-9:END: used = 3
Thread-6:BEGIN: used = 3
Thread-6:END: used = 3
Thread-1:BEGIN: used = 3
Thread-8:END: used = 3
Thread-9:BEGIN: used = 3
Thread-3:END: used = 3
Thread-4:BEGIN: used = 3
Thread-1:END: used = 3
Thread-4:END: used = 2
Thread-8:BEGIN: used = 2
Thread-0:BEGIN: used = 3
Thread-9:END: used = 3
Thread-9:BEGIN: used = 3
Thread-8:END: used = 3
Thread-9:END: used = 2
Thread-7:BEGIN: used = 2
Thread-0:END: used = 2
Thread-5:BEGIN: used = 2
Thread-6:BEGIN: used = 3
Thread-6:END: used = 3
Thread-7:END: used = 2
Thread-5:END: used = 1
Thread-3:BEGIN: used = 1
Thread-3:END: used = 1
Thread-0:BEGIN: used = 1
Thread-7:BEGIN: used = 2
Thread-8:BEGIN: used = 3
Thread-0:END: used = 3
Thread-2:BEGIN: used = 3
Thread-8:END: used = 3
Thread-2:END: used = 2
Thread-7:END: used = 1
Thread-0:BEGIN: used = 1
Thread-7:BEGIN: used = 2
Thread-4:BEGIN: used = 3
Thread-7:END: used = 3
Thread-0:END: used = 2
Thread-4:END: used = 1
Thread-2:BEGIN: used = 1
Thread-1:BEGIN: used = 2
Thread-1:END: used = 2

本文深入探讨了单线程执行模式(singlethreadexecution),解释了其概念与实现方式,重点在于如何使用synchronized关键字来保护共享资源,避免多线程环境下的死锁问题,并通过Java代码示例展示了如何利用Semaphore控制资源的并发访问。
388

被折叠的 条评论
为什么被折叠?



