2012-01-05 12 views
5

Tôi có câu hỏi trong đó mỗi chủ đề được cập nhật theo một chủ đề khác nhau. Vì vậy, bất cứ khi nào chủ đề được cập nhật nó tương ứng cập nhật người quan sát với thông tin mới. Tuy nhiên, nếu danh sách các nhà quan sát là dài, nó sẽ đòi hỏi một thời gian để cập nhật tất cả các nhà quan sát. Hãy suy nghĩ về một chủ đề được cập nhật rất thường xuyên. Trong khi chủ đề đang cập nhật các nhà quan sát, đối tượng "chủ thể" bị khóa và do đó không thể được cập nhật bởi một chủ đề khác. Điều này sẽ tạo ra lưu lượng thông tin cho chủ đề hoặc gây mất thông tin.Mẫu quan sát đa luồng

Bạn có biết bất kỳ vấn đề nào được xử lý trong môi trường đa luồng không? Ngoài ra, bất cứ ai có thể giới thiệu một số cuốn sách về lập trình song song với C + +?

+0

nó này một câu hỏi lý thuyết? bởi vì có thể có các giải pháp khác cho vấn đề của bạn mà không liên quan đến việc sử dụng cái gọi là 'mẫu'. – INS

+0

chủ đề không cần phải "bị khóa" nếu thông tin được giữ không thay đổi trong quá trình cập nhật của người quan sát hoặc thay đổi không có bất kỳ hậu quả nào. Hãy nghĩ về một tệp chỉ đọc làm ví dụ. Theo như tôi có thể nghĩ, Multi-luồng sẽ không giải quyết được vấn đề nếu tôi đã hiểu điểm của bạn đúng cách.Ngoài ra các chủ đề khác có thể đợi cho đến khi chủ đề có sẵn trở lại và không trở lại sau khi hết thời gian chờ và sẽ không có "mất thông tin" nhưng điều đó phụ thuộc vào bối cảnh khó tưởng tượng bởi lượng thông tin bạn đã cung cấp trong mô tả vấn đề của bạn. – Barracuda

Trả lời

6

Cân nhắc việc sử dụng producer-consumer queues hoặc message queues. Ví dụ của bạn, bạn có thể sử dụng hàng đợi theo hai cách:

  1. Thay đổi đối tượng được xếp hàng đợi. Khi một cái gì đó cập nhật chủ đề, nó sẽ đặt trạng thái mới trong hàng đợi và trả về ngay lập tức. Bằng cách này, trình cập nhật không chặn trong khi người quan sát được thông báo. Bạn sẽ cần một chuỗi liên tục khử đi các thay đổi trạng thái và cập nhật các nhà quan sát.

  2. Thông báo cho Người quan sát được xếp hàng đợi. Mỗi người quan sát có một hàng đợi nơi các thông báo thay đổi trạng thái chủ đề được đăng.

Nếu bạn đang sử dụng thư viện Qt, bạn có thể sử dụng các tín hiệu & khe cơ chế với kiểu Qt::QueuedConnection kết nối. Khe cắm đi qua hàng đợi sự kiện của người nhận và được thực thi trong luồng của người nhận. Bằng cách này, người gửi không chặn trong khi người nhận thực hiện các vị trí tương ứng của họ.

Chương trình của bạn có thể là ứng cử viên tốt cho số Actor model (paradigm). Dưới đây là một số C thư viện ++ mà thực hiện các mô hình diễn viên:

chương trình của bạn có thể cũng là một ứng cử viên tốt cho mô hình Dataflow. Hãy xem thư viện được đề xuất Boost Dataflow, hỗ trợ threading.


Tôi không có một cuốn sách giới thiệu, nhưng hãy kiểm tra Herb Sutter series of Dr Dobbs articles trên C++ đồng thời.

+0

Btw: libcppa hỗ trợ xuất bản/đăng ký truyền thông nhóm dựa trên cho các diễn viên. Đối tượng có thể dễ dàng được mô hình hóa như một nhóm địa phương. Bất kỳ số lượng chủ đề/diễn viên (nhà xuất bản) đang gửi đến nhóm, bất kỳ số lượng chủ đề/diễn viên (người nhận) có thể nhận được chỉ bằng cách tham gia nhóm. – neverlord

1

Tôi đã viết một mô hình quan sát Multithreaded trong Java

 

    import java.lang.reflect.Method; 
    import java.util.List; 
    import java.util.Map; 
    import java.util.Map.Entry; 

    /** 
    * An observer pattern that allows listeners to register(), unregister() in 
    * multiple threads and also notify listeners in another thread. 
    * 
    * A HashMap keeps track of the listeners and their status (active, obsolete). 
    * When a listener unregister, its entry is marked as obsolete in this map. 
    * 
    * During firing of an event, the observer notifies all the listeners that are 
    * active, the active status will be stored in a Boolean that's synchronized so 
    * rare race conditions like calling notify on an active listener that has just 
    * turned obsolete will not happen. 
    * 
    * 
    */ 
    public class MultithreadedObserverPattern { 

     interface Handler { 
      void handleEvent(T listener); 
     } 

     class BooleanHolder { 
      boolean val; 

      BooleanHolder(boolean v) { 
       val = v; 
      } 

      void set(boolean v) { 
       val = v; 
      } 

      boolean get() { 
       return val; 
      } 
     } 

     Map listeners = new HashMap(); 

     public void register(AbstractListener l) { 
      synchronized (listeners) { 
       listeners.put(l, new BooleanHolder(true)); 
      } 
     } 

     public void unregister(AbstractListener l) { 
      synchronized (listeners) { 
       BooleanHolder status = listeners.get(l); 
       if (status != null) { 
        // notify call also syncing on status 
        synchronized (status) { 
         status.set(false); 
        } 
       } 
       // set to false 
      } 
     } 

     public void notifyAll(Handler handler) { 
      // here we do not synchroznie on listeners to avoid tricky lock situations 
      // make a copy of the map 
      List> activeListeners = new ArrayList>(); 
      List inactiveListeners = new ArrayList(); 

      synchronized (listeners) { 
       for (Entry entry : listeners.entrySet()) { 
        if (entry.getValue().get()) { 
         activeListeners.add(entry); 
        } else { 
         inactiveListeners.add(entry.getKey()); 
        } 
       } 
      } 
      // call the method on active listener 
      // 
      for (Entry e : activeListeners) { 
       BooleanHolder status = e.getValue(); 
       // remove those listeners that are no longer active 
       synchronized (status) { 
        if (status.get()) { 
          handler.handleEvent(e.getKey()); 
        } 
       } 
      } 

      synchronized (listeners) { 
       // remove inactive listeners 
       for (AbstractListener l : inactiveListeners) { 
        listeners.remove(l); 
       } 
      } 
     } 
    }