> From: "Dain Ironfoot" <vicvanda...@gmail.com>
> To: "mechanical-sympathy" <mechanical-sympathy@googlegroups.com>
> Sent: Saturday, June 4, 2022 12:53:55 AM
> Subject: Compute in a lock free way

> Hello,
> I am writing a class to calculate average of prices. We use it to generate
> buy/sell signal for some financial instruments therefore latency is crucial.
> Prices are sent via different threads therefore class needs to be thread-safe.

> Am I correct in understanding that I have to use a lock to make the two
> operations (adding and incrementing) atomic? I have looked at
> AtomicLong/LongAdder/LongAccumulator but looks like they can only sum the
> numbers atomically.

> In other words, there is no way to do this in a lock-free manner?

you can group them in an object and do a CAS (see VarHandle.compareAndSet) on 
the references 

record Stat(BigDecimal sum, int count) { } 

public final class Computer { 
private volatile Stat stat; 

public void add(double value) { 
// do a CAS between stat and new Stat(BigDecimal.valueOf(value), stat.count + 
1) 
} 
} 

BTW in your example, rwLock, readLock and writeLock should be declared final to 
avoid any publication issues, 
see [ 
https://stackoverflow.com/questions/1621435/not-thread-safe-object-publishing | 
https://stackoverflow.com/questions/1621435/not-thread-safe-object-publishing ] 

regards, 
RĂ©mi 

> Thank you!

> public final class Computer{

> private ReentrantReadWriteLock rwLock;
> private ReadLock readLock;
> private WriteLock writeLock;

> private BigDecimal sum;
> private int count;

> public AverageCalculatorThreadSafeImplementation2( ){
> this.rwLock = new ReentrantReadWriteLock();
> this.readLock = rwLock.readLock();
> this.writeLock = rwLock.writeLock();
> this.sum = new BigDecimal(0);
> }

> public final void add( double value ){
> writeLock.lock();
> try{
> sum = sum.add( BigDecimal. valueOf (value) );
> ++count;
> }finally{
> writeLock.unlock();
> }
> }

> public final double compute( ){
> readLock.lock();
> try{
> return sum.divide(BigDecimal. valueOf (count)).doubleValue();
> }finally{
> readLock.unlock();
> }
> }
> --
> You received this message because you are subscribed to the Google Groups
> "mechanical-sympathy" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email
> to [ mailto:mechanical-sympathy+unsubscr...@googlegroups.com |
> mechanical-sympathy+unsubscr...@googlegroups.com ] .
> To view this discussion on the web, visit [
> https://groups.google.com/d/msgid/mechanical-sympathy/2d083587-2ee1-4f8f-a7ee-a99062a6ef5cn%40googlegroups.com?utm_medium=email&utm_source=footer
> |
> https://groups.google.com/d/msgid/mechanical-sympathy/2d083587-2ee1-4f8f-a7ee-a99062a6ef5cn%40googlegroups.com
> ] .

-- 
You received this message because you are subscribed to the Google Groups 
"mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to mechanical-sympathy+unsubscr...@googlegroups.com.
To view this discussion on the web, visit 
https://groups.google.com/d/msgid/mechanical-sympathy/145240008.2007500.1654332340634.JavaMail.zimbra%40u-pem.fr.

Reply via email to