👳我亲爱的各位大佬们好😘😘😘
♨️本篇文章记录的为 线程同步模式之保护性暂停 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。
♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️🧡💛
👨🔧 个人主页 : 阿千弟何为保护性暂停
保护性暂停是一种同步模式,用于保护共享资源的完整性。在多线程或多进程环境中,如果多个线程或进程同时访问共享资源,可能会导致数据不一致或者竞态条件等问题。为了避免这种情况,可以使用保护性暂停来保护共享资源。
实现方式:
在访问共享资源之前,先获取一个锁,然后再访问共享资源。如果锁已经被其他线程或进程占用,则当前线程或进程会被阻塞,直到锁被释放为止。在访问完共享资源之后,需要释放锁,以便其他线程或进程可以继续访问共享资源。
作用:
保护性暂停可以保证共享资源的完整性,但是也会带来一定的性能开销。因为每个线程或进程在访问共享资源之前都需要获取锁,如果锁的竞争比较激烈,就会导致线程或进程的等待时间增加,从而影响系统的性能。因此,在使用保护性暂停时,需要权衡保证数据完整性和系统性能之间的关系,选择合适的锁机制和并发控制策略。
- 具体定义:
即 Guarded Suspension
(被监视的挂起),用在一个线程等待另一个线程的执行结果
要点
- 有一个结果需要从一个线程传递到另一个线程,让他们关联同一个 GuardedObject
- 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(见生产者/消费者)
- JDK 中,join 的实现、Future 的实现,采用的就是此模式
- 因为要等待另一方的结果,因此归类到同步模式
代码实现
GuardedObject
@Slf4j
public class GuardedObject {
private Object response;
private final Object lock = new Object();
//直到收到返回结果会被唤醒, 死等
public Object get(){
synchronized (lock){
while (response==null){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
return response;
}
//接受结果的等待时间为mills, 如果该期间仍然没有接受到返回结果, 则
public Object get(long mills){
// 1) 记录最初时间
long beginTime = System.currentTimeMillis();
// 2) 已经经历的时间
long passTime = 0;
synchronized (lock){
while (response==null){
// 4) 假设 millis 是 1000,结果在 400 时唤醒了,那么还有 600 要等
long waitTime = mills - passTime;
if (waitTime <= 0){
break;
}
try {
lock.wait(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 3) 如果提前被唤醒,这时已经经历的时间假设为 400
passTime = System.currentTimeMillis() - beginTime;
log.debug("timePassed: {}, object is null {}",passTime, response == null);
}
return response;
}
}
public void complete(Object response){
synchronized (lock){
// 条件满足,通知等待线程
this.response = response;
lock.notifyAll();
}
}
public static void main(String[] args) {
GuardedObject guardedObject = new GuardedObject();
new Thread(()->{
try {
List<String> response = Downloader.download();
log.info("下载完成");
guardedObject.complete(response);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
log.info("正在下载");
Object response = guardedObject.get(500);
if(response!=null){
log.debug("get response: [{}] lines", ((List<String>) response).size());
} else {
log.debug("can't get response");
}
}
}
下载案例demo
public class Downloader {
public static List<String> download() throws IOException {
HttpURLConnection conn = (HttpURLConnection) new URL("https://www.baidu.com/").openConnection();
List<String> lines = new ArrayList<>();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
}
return lines;
}
}
测试,超时
17:41:21.194 [main] INFO com.jrm.juc.GuardedObject - 正在下载
17:41:21.700 [main] DEBUG com.jrm.juc.GuardedObject - timePassed: 503, object is null true
17:41:21.701 [main] DEBUG com.jrm.juc.GuardedObject - can't get response
17:41:25.560 [Thread-0] INFO com.jrm.juc.GuardedObject - 下载完成
Process finished with exit code 0
如果这篇【文章】有帮助到你💖,希望可以给我点个赞👍,创作不易,如果有对Java后端或者对
spring
,分布式
,云原生
感兴趣的朋友,请多多关注💖💖💖
👨🔧 个人主页 : 阿千弟