线程同步模式之保护性暂停

简介: 保护性暂停是一种同步模式,用于保护共享资源的完整性。在多线程或多进程环境中,如果多个线程或进程同时访问共享资源,可能会导致数据不一致或者竞态条件等问题

👳我亲爱的各位大佬们好😘😘😘
♨️本篇文章记录的为 线程同步模式之保护性暂停 相关内容,适合在学Java的小白,帮助新手快速上手,也适合复习中,面试中的大佬🙉🙉🙉。
♨️如果文章有什么需要改进的地方还请大佬不吝赐教❤️🧡💛
👨‍🔧 个人主页 : 阿千弟

何为保护性暂停

保护性暂停是一种同步模式,用于保护共享资源的完整性。在多线程或多进程环境中,如果多个线程或进程同时访问共享资源,可能会导致数据不一致或者竞态条件等问题。为了避免这种情况,可以使用保护性暂停来保护共享资源。

实现方式:

在访问共享资源之前,先获取一个锁,然后再访问共享资源。如果锁已经被其他线程或进程占用,则当前线程或进程会被阻塞,直到锁被释放为止。在访问完共享资源之后,需要释放锁,以便其他线程或进程可以继续访问共享资源。

作用:

保护性暂停可以保证共享资源的完整性,但是也会带来一定的性能开销。因为每个线程或进程在访问共享资源之前都需要获取锁,如果锁的竞争比较激烈,就会导致线程或进程的等待时间增加,从而影响系统的性能。因此,在使用保护性暂停时,需要权衡保证数据完整性和系统性能之间的关系,选择合适的锁机制和并发控制策略。

  1. 具体定义:

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, 分布式, 云原生感兴趣的朋友,请多多关注💖💖💖
👨‍🔧 个人主页 : 阿千弟

目录
相关文章
|
5月前
|
存储 Linux 调度
Linux多线程【线程控制】
Linux多线程【线程控制】
43 0
|
1天前
LabVIEW中使用队列,通知器,信号量或集合点时的潜在竞争情况
LabVIEW中使用队列,通知器,信号量或集合点时的潜在竞争情况
|
2月前
|
消息中间件 Java
保护性暂停模式
保护性暂停模式
21 0
|
10月前
|
消息中间件 Java
同步模式之保护性暂停
同步模式之保护性暂停
|
10月前
多线程的几种状态
多线程的几种状态
|
11月前
|
安全 Java 调度
【Java并发编程 五】线程生命周期及状态切换
【Java并发编程 五】线程生命周期及状态切换
62 0
|
11月前
|
Java 程序员
同步模式之顺序控制线程执行
同步模式是指在多线程编程中,为了保证线程之间的协作和正确性,需要对线程的执行顺序进行控制。顺序控制线程执行是一种同步模式,它通过控制线程的等待和唤醒来实现线程的有序执行。
104 0
同步模式之顺序控制线程执行
|
消息中间件 Java
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式(一)
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式(一)
|
缓存 监控 安全
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式(二)
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式
《JUC并发编程 - 模式篇》保护性暂停模式 | 顺序控制模式 | 生产者消费者模式 | 两阶段终止模式 | Balking模式 | 享元模式(二)
|
设计模式 Java
保护性暂停
如何实现线程同步和异步