I believe you are most likely right about the TryLock(0 not being needed but I am not 100% sure. I guess eventually I will investigate it.
I am also puzzled by the race detector behavior here, FWIIW. :) And no worries, this sounded like something useful to write. It goes without saying but feel free to use it as you see fit. -Bruno On Fri, Jan 31, 2025 at 12:19 PM robert engels <reng...@ix.netcom.com> wrote: > But the lock shouldn’t be necessary I don’t think? The atomic read > provides a happens before relationship - which is why removing it didn’t > change anything. > > I am just surprised the race detector does not complain - given my > knowledge of how the race detector works it seems it should. > > Thanks for writing all of the code - interesting problem. The stamped lock > is super efficient for many readers, rare writers - without resorting to > copy on write or mutexes. > > On Jan 31, 2025, at 11:13 AM, Bruno Albuquerque <b...@gmail.com> wrote: > > I did not look at the java code (I went for the description on the link > you posted). > > The idea in TryOptimisticRead() is that the TryLock() helps avoiding > reordering/cache effects. Consider this: > > Reader 1 calls TryOptimisticRead() and reads the stamp (let's say it's > 100). > > Writer acquires the write lock, increments data, and increments the stamp > to 101. > > Writer releases the write lock. > > Reader 1 proceeds to read the shared data. Crucially, due to memory > reordering or caching effects, it might still see the old value of data, > even though the writer has already updated it. > > Reader 1 calls Validate(100). The stamp is now 101, so Validate() returns > false. > > The second to last step is hypothetical and I did not test it. In fact, I > just removed the TryLock() and returned the result of Adduint32 directly > and the race detector still did not complain (not sure if the results are > the expected ones. More testing would be needed). In other words, this > still seems to work: > > func (sl *StampedLock) TryOptimisticRead() uint64 { > return atomic.LoadUint64(&sl.stamp) > } > > > On Fri, Jan 31, 2025 at 12:05 PM robert engels <reng...@ix.netcom.com> > wrote: > >> Your code seems substantially different than the Java implementation. For >> instance, in your tryOptimisticRead(), you take a lock - the Java version >> has no locking in that method (on a volatile, aka atomic read) - although I >> am not sure why you are taking the lock. >> >> func (sl *StampedLock) TryOptimisticRead() uint64 { >> stamp := atomic.LoadUint64(&sl.stamp) >> if sl.mu.TryLock() { >> sl.mu.Unlock() >> return stamp >> } >> return stamp >> } >> >> // Java - state is a “volatile” integer >> >> public long tryOptimisticRead() { >> long s; >> return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L; >> } >> >> >> On Jan 31, 2025, at 10:51 AM, Bruno Albuquerque <b...@gmail.com> wrote: >> >> Ops. There was a bug due to left over of me testing. Here is a fixed >> version: >> >> https://go.dev/play/p/UuIWVlV0UTN >> >> Also, don't try to run in the playground as this runs forever (it could >> be changed but I am lazy). >> >> -Bruno >> >> >> On Fri, Jan 31, 2025 at 11:31 AM Bruno Albuquerque <b...@gmail.com> wrote: >> >>> This seemed expected to me but I went ahead and created a Go >>> implementation (which might not be 100% correct so take it for what it >>> will) and I was surprised that the race detector did not really complain >>> about anything. >>> >>> https://go.dev/play/p/R1alMCc-xN9 >>> >>> -Bruno >>> >>> >>> On Fri, Jan 31, 2025, 6:13 AM Robert Engels <reng...@ix.netcom.com> >>> wrote: >>> >>>> Hi, >>>> >>>> Do you think it is possible to implement a stamped lock in Go >>>> https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/StampedLock.html >>>> ? >>>> >>>> It would seem that the Go race detector would always report the >>>> “optimistic read” mode as a data race? >>>> >>>> (The docs state for Java that the values can be wildly inconsistent >>>> when the optimistic read fails). >>>> >>>> Ideas on how to implement in Go? >>>> >>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "golang-nuts" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to golang-nuts+unsubscr...@googlegroups.com. >>>> To view this discussion visit >>>> https://groups.google.com/d/msgid/golang-nuts/FBEB055A-2B84-4738-AE22-C22ABAC8C4A9%40ix.netcom.com >>>> <https://groups.google.com/d/msgid/golang-nuts/FBEB055A-2B84-4738-AE22-C22ABAC8C4A9%40ix.netcom.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/CAEd86TwQ_HzVt_H3rA84PWb1jdt%2BJBjQoD2Pq4VPDCVbS7d1yg%40mail.gmail.com >> <https://groups.google.com/d/msgid/golang-nuts/CAEd86TwQ_HzVt_H3rA84PWb1jdt%2BJBjQoD2Pq4VPDCVbS7d1yg%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> >> >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAEd86Tw_Aj0Rh-pfK24KJ21P_Z1pZY2R2g9Jg9u_5ttDyrvDUQ%40mail.gmail.com.