![]() |
Copyright © TIBCO Software Inc. All Rights Reserved |
• With all modes, for reads. If you want to read the latest version of a concept in one agent at the same time that another agent might create or update the same concept, mediate the reads through the same global lock that was used when creating or updating the concept. This is done using an event preprocessor and, for Cache Plus Memory, a subscription preprocessor.
• With Cache Only mode, for writes. Global locking is done using an event preprocessor.
• With Concurrent RTC (even with In Memory OM or Memory Only mode), for writes Multiple RTCs could use the same in-memory object, therefore it needs to be protected using a lock. Use a local lock, not a global lock.
• With Cache Plus Memory mode, for writes, and for subscription RTCs. These RTCs run internally to keep the Rete networks on each agent synchronized with the cache). Locking is done using a subscription preprocessor. It uses the same locking key (string) as in the event preprocessor, if one was used.
• With state modeler, for timeouts. State modeler timeouts do not go through an event preprocessor, so locking is done a different way. This is explained in TIBCO BusinessEvents Data Modeling Developer’s Guide.Note that event preprocessors are multi threaded (see Event Preprocessors for more details).Cluster.DataGrid.Lock(Customer@extId, -1, false);
4. Agent A sends a change notification to all other agents that have subscribed to cluster notifications for this object. Agent B receives the notification, and calls the subscription preprocessor function. It contains the same function shown in step 1 above. It uses the same locking string. Agent B acquires the lock (that is the function returns true). The agent updates the Rete network with the changes (using a “subscription RTC”). It will release the lock when the subscription RTC is complete.If you want to acquire the lock only within the agent, set LocalOnly to true. Set the LocalOnly parameter to false to acquire a cluster wide lock. For example if you are only concerned about the preprocessor threads in one agent, you can use a local lock.The worker thread that calls the lock() function is the only thread that gets blocked.You can use the corresponding UnLock() function for cases where the automatic unlocking does not meet your needs.
The Cluster.DataGrid.Lock() and Cluster.DataGrid.UnLock() functions are available in event and subscription preprocessors and in rules. However, in general it is not a good idea to use lock() in rules as the order of processing of rules is not guaranteed.You can call Cluster.DataGrid.UnLock() in a rule only when concurrent RTC is used.The example LockExample (in BE_HOME/examples/standard) demonstrates these points, showing use of locks to prevent race conditions.
• Choose an appropriate key for lock(). Note that lock() does not lock any entity or object as such. The purpose of lock() is to ensure sequential processing of related set of objects, but yet ensure concurrent processing of unrelated objects. For example, you want to process messages related to one customer sequentially across the cluster, but want to process messages for different customers in parallel. In this case you could use the customer ID as the key used for lock(). This ensures that all messages for a given customer ID are processed sequentially.
• Always check the return value of lock() and if false, either retry or handle it as an error. Don't let application logic proceed if it returns false. Doing so may result in lost updates or stale reads or other such data inconsistencies.
•
•
• Use lock() even for read-only operations. If you do not you may get “Inconsistent Database” messages, for example, if there are concurrent deletes elsewhere in other threads or agents.
• In general, avoid using lock() in a rule. Since rule order of execution is not guaranteed such usage may lead to deadlocks.If the ordering of keys is not guaranteed, it may lead to a deadlock in a multi-agent or concurrent RTC (multi-threaded) environment. For this reason, avoid use of lock() in a loop, where the intention is to process multiple messages. There are other ways to achieve this, for example, using the assertEvent_Async() function.
![]() |
Copyright © TIBCO Software Inc. All Rights Reserved |