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.

Reply via email to