Path: csiph.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Robert Klemme Newsgroups: comp.lang.java.programmer Subject: Re: Library for Escalable Locks, Slimmest API? Date: Sun, 14 Aug 2016 12:13:47 +0200 Lines: 125 Message-ID: References: <26c75c11-5955-45a6-919d-3de1255c9c15@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net y4YaVu0x2nj255FipiSlFAjE4ehg5zs8XgweE0hPD+RUqA3FM= Cancel-Lock: sha1:cQ1YcX53nB+LcMFdy/J1hotqTuI= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 In-Reply-To: Xref: csiph.com comp.lang.java.programmer:35322 On 14.08.2016 11:42, j4n bur53 wrote: > Robert Klemme schrieb: Thank you for the following explanations! >> So are you writing the application or not? > > The application I need the locks for is a parallel Prolog > class loader. This loader will not have any guarantees > for deadlock-freeness. > > If a deadlock happens, one of the threads will time-out > and the other thread will win. The parallel Prolog class > loader is already in production for a couple of years. > > I am now doing a refinement, the old version was unsing > a mutex the new version will use read write pairs. The > refinement has to do with a performance optimization. > > The performance optimization is such that Prolog can > distinguish between static and dynamic predicates. Do > avoid locks at runtime in static predicates I need a more > complicated Prolog class loader. > > The more complicated Prolog class loader will use read > locks during predicate lookup, and write locks during > Prolog text consult. As a new benefit it will not anymore > happen that predicates see gradually loaded predicates. > > Currently it is possible that a thread that does not do > the loading of the Prolog text, will see how a predicate > gradually is loaded. The new read lock will prevent this. > > On the other hand the thread that does the loading, and > which has the write lock, should be permitted to also > read the predicate. This is needed durig loading. That is possible with a ReadWriteLock: if you hold the write lock the resource is yours to write but of course also to read. > So here in the following is a map what new scenarios are > needed, and how the different locks support that, and why I > need new synchronization primitives: > > Thread A: Re-Loads Text T > Thread B1, .. Thread Bn: Executes Text T This sounds as if there are dedicated threads for loading. If this is the case then acquiring the write lock right away for these would be sufficient it seems. You only then could face starvation issues which you can remedy by using fair mode: http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html > <>: Atomic > RW: Ordinary Read Write Lock Pair > ERW: Escalable Read Write Lock Pair > > Situation Mutex RW ERW > No(1) Yes Yes > > > No(1) No(2) Yes > > > No(1) No(2) Yes > > > (1) mutex cannot be used, since mutex does > not allow multiple readers > (2) ordinary read write pair cannot be used, > since ordinary read write pair does not > allow same thread to be reader and write In case there are no dedicated loading threads: If you are trying to optimize this, then a different scheme might work as well: you could hold the resource in an AtomicReference. Whenever a thread reads null, it needs to load the resource and update the reference. The object representing the loaded file content then should of course be immutable. Downside is that sometimes multiple threads might be reading but you can ensure that only one of them updates the reference. Alternatively the algorithm without any need for lock escalation could be like this (pseudo code): final boolean needsLoading acquire r-l needsLoading = resourceNeedsLoading() if (!needsLoading) { useIt() } release r-l if (needsLoading) { acquire w-l if ( resourceNeedsLoading() ) { loadFromFile() updateResource() } release w-l acquire rl assert !resourceNeedsLoading() useIt() release rl } resourceNeedsLoading() could then either check whether the resource has been loaded at all or also include modified time checks on the file. I do not know though how consistency requirements are in your application on a larger scale - especially since you mention "re-loading". Under which circumstances is a file reloaded? Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/