Github user aledsage commented on a diff in the pull request:

    https://github.com/apache/brooklyn-server/pull/835#discussion_r142912453
  
    --- Diff: 
core/src/main/java/org/apache/brooklyn/core/sensor/AttributeMap.java ---
    @@ -139,9 +139,18 @@ private void checkPath(Collection<String> path) {
         }
     
         public <T> T update(AttributeSensor<T> attribute, T newValue) {
    -        T oldValue = updateWithoutPublishing(attribute, newValue);
    -        entity.emitInternal(attribute, newValue);
    -        return oldValue;
    +        // 2017-10 this was unsynched which meant if two threads updated
    +        // the last publication would not correspond to the last value.
    +        // could introduce deadlock but emit internal and publish should
    +        // not seek any locks. _subscribe_ and _delivery_ might, but they
    +        // won't be in this block. an issue with 
_subscribe-and-get-initial_
    +        // should be resolved by initial subscription queueing the 
publication
    +        // to a context where locks are not held.
    +        synchronized (values) {
    --- End diff --
    
    TL;DR: I agree this is fine. Below are some notes from digging around in 
the synchronization code.
    
    Looking at the other synchronization blocks, `emitInternal` will 
synchronize on `EntityManagementSupport` instance (when it calls 
`getSubscriptionContext()`. It will then call `publish` which will synchronize 
on `LocalSubscriptionManager` instance (in `getSubscriptionsForEntitySensor`).
    
    However, I think we can trust both the `EntityManagementSupport` and the 
`LocalSubscriptionManager` to not call out to alien code while holding a lock 
on itself. Therefore we should be safe in that respect.
    
    The code in `AbstractEntity` and `AbstractGroupImpl` looks a bit scary, 
where it first gets the lock on this `values` object and then on either 
`abstractGroup.members` or `abstractEntity.children` (but it's kind-of 
understandable why it does that and how that pattern avoids it; it would just 
be nicer if instead we didn't call out to alient code while holding the lock on 
`values` - but that's a bigger discussion than for this PR):
    ```
            synchronized (getAttributesSynchObjectInternal()) {
                synchronized (members) {
    ```



---

Reply via email to