具有共享资源的观察者模式中的 C# 竞争条件预防

笔记本电脑

我有一个线程 WebListener,它使用最新传入的消息更新公共变量。我已经用观察者模式实现了这个类,所以我可以在收到新消息时通知订阅者。然后每个订阅者可以决定是否从公共变量中检索消息。

我关心的场景是:

  1. WebListner 收到消息“a”
  2. WebListener 写入消息“a”
  3. WebListener 通知订阅者收到的消息“a”
  4. 订阅者收到消息“a”的通知
  5. WebListener 收到另一条消息“b”
  6. WebListener 用“b”覆盖消息“a”
  7. WebListener 通知订阅者收到的消息“b”
  8. 订阅者读取消息 'a' 但实际上得到了 'b'注意 - 这是 100% 好的 - 我们希望收到最新消息 ( b)
  9. 订阅者读取消息“b”并再次获得“b”。注意 - 这不应该返回b- 它应该不返回任何内容或抛出异常

**编辑:订阅者在收到通知后每次回想起一条消息时都应该收到一条新消息。这是我尝试使用随通知传递的令牌来解决的问题。如果来自先前通知的消息已被覆盖,则结果应该是未检索到该消息。在任何阶段,我都不希望检索当前消息以外的消息。**

以最有效的方式防止这种情况的最佳方法是什么?

我想生成一个唯一的令牌并将其与通知一起发送给订阅者以进行比较令牌 - > 读取值类型的操作,但这会导致 WebListener 覆盖比较和读取操作之间的值的竞争条件问题。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Threading;

// Observer design pattern allows objects created from classes that inherit from 
// IObserver to be notified when an event is triggered when subscribed. 
// In this case, the event is when a HTTP message is received on the listenport endpoint.

public interface IObserver
{
    //Receive update from subject
    void Update(ITopic topic);
}

public interface ITopic
{
    //Subscribe an observer to the topic
    void Subscribe(IObserver observer);

    //Unsubscribe a subscriber from the topic
    void Unsubscribe(IObserver observer);

    //Notify all subscribers of an event
    void Notify();
}

// WebListener listens for incoming http messages on the listenport endpoint and notifies subscribers.
// Subscribers can access the message through the public method GetMessage.
public class WebListener : MonoBehaviour, ITopic
{
    string listenport = "http://192.168.1.3:8080";

    private HttpListener listener;
    private Thread listenerThread;

    HttpListenerRequest message;

    void Start()
    {
        listener = new HttpListener();
        listener.Prefixes.Add(listenport);
        listener.Start();

        listenerThread = new Thread(startListener);
        listenerThread.Start();

        Debug.Log("WebListener: Listener started");
    }

    private void startListener()
    {
        while (true)
        {
            var result = listener.BeginGetContext(ListenerCallback, listener);
            result.AsyncWaitHandle.WaitOne();
        }
    }

    private void ListenerCallback(IAsyncResult result)
    {
        var context = listener.EndGetContext(result);
        ReceiveMessage(context);
        context.Response.Close();
    }

    private void ReceiveMessage(HttpListenerContext context)
    {
        message = context.Request;
    }

    // SUBSCRIBERS WILL CALL THIS TO RETRIEVE MESSAGE
    public HttpListenerRequest GetMessage()
    {
        return message;
    }

    private List<IObserver> _observers = new List<IObserver>();

    // Implement ITopic interface methods
    public void Subscribe(IObserver observer)
    {
        this._observers.Add(observer);
        Debug.Log("WebListener: Added Subscriber");
    }

    public void Unsubscribe(IObserver observer)
    {
        this._observers.Remove(observer);
        Debug.Log("WebListener: Removed Subscriber");
    }

    public void Notify()
    {
        //WAS GOING TO GENERATE TOKEN HERE AND PASS IN THE UPDATE FUNCTION BUT THIS WILL CREATE RACE-CONDITION.
        Debug.Log("WebListener: Notifying subscribers of incoming message");
        foreach (var observer in _observers)
        {
            observer.Update(this);

        }
    }
}
阿列克谢·列文科夫

您无法真正更新全局状态并期望侦听器神奇地获得一致的历史值而不以某种方式存储它们。

选项:

  • 将听众的期望更改为“全局状态发生变化,需要检查”
  • 在事件中将更改记录发送到侦听器
  • 每个侦听器都有更改队列
  • 使状态不可变并将当前状态发送给事件中的侦听器
  • 虽然它可能对您的特定情况没有用,但同步接收和通知调用以等待所有“通知”处理程序完成,然后再允许下一次“接收”是一个选项(由Jonathon K建议

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

具有泛型的C#观察者模式

来自分类Dev

C ++中良性竞争条件的保证

来自分类Dev

C#中的观察者模式

来自分类Dev

来自C#中的线程的ProducerConsumerQueue中的竞争条件

来自分类Dev

SqlCommand在C#中创建数据库竞争条件

来自分类Dev

访问C#中的多线程列表时的竞争条件

来自分类Dev

c++ std::thread 中的竞争条件或内存损坏

来自分类Dev

ConcurrentBitSet中的竞争条件

来自分类Dev

实现C ++ -lua观察者模式?

来自分类Dev

实现观察者模式C ++

来自分类Dev

C#中是否有“向后”观察者的概念

来自分类Dev

C# 中的简单 SQLite ORM,代码有效但如何解决竞争条件

来自分类Dev

在PostgreSQL中处理竞争条件

来自分类Dev

在 OpenMP 中避免竞争条件?

来自分类Dev

有条件的点击动作预防

来自分类Dev

解决的睡眠方法将程序线程挂在C pthread中(竞争条件,它与睡眠无关)

来自分类Dev

使用C的TCP套接字中的人为延迟,用于竞争条件开发

来自分类Dev

在 C++ 中递增和递减全局变量时的竞争条件

来自分类Dev

C多线程:竞争条件场景

来自分类Dev

Mongo:在条件更新中消除竞争条件

来自分类Dev

在C#中同步共享资源的集合

来自分类Dev

在C#中同步共享资源的集合

来自分类Dev

当只有一个线程向c ++中的bool变量写入时,是否存在竞争条件?

来自分类Dev

使用C#MVC实现观察者模式

来自分类Dev

使用 Cocoa 在 Objective-C 中的事件处理程序中删除本地事件监视器的竞争条件

来自分类Dev

带有文件加载的竞争条件

来自分类Dev

此功能是否没有竞争条件?

来自分类Dev

有竞争条件的JFreeChart addBin吗?

来自分类Dev

如何在Java中重现竞争条件?

Related 相关文章

热门标签

归档