A’ would then be susceptible to the original “reasoning difficulties” without any locking. I think it shows that any complex function, especially those with recursion, have the same difficulties. 

Due to sequential consistency, A’ must be correct, since a non-reentrant lock forces a single thread of execution - making A’ and A equivalent. 

A holding the lock for the length of A’ communicates that A’ is inside the critical section and must be careful to preserve invariants. A’ internally locking a reentrant lock is ambiguous with respect to invariant expectations.

The practical implications are as important as the theoretical. There’s inherent complexity in both - non reentrant locks tends to surface complexity and make the behaviors/assumptions more obvious. 

Very, very occasionally reentrant locks are worth the ambiguity they introduce, but primarily in callback heavy code (which Go doesn’t encourage as much as other languages/APIs).

-eli

On Nov 2, 2022, at 7:49 AM, Eli Lindsey <e...@siliconsprawl.com> wrote:

Reentrant locks make any given critical section harder to understand because you must also understand the calling pattern that led there to know which invariants have been upheld and which may have been violated due to a still-in-progress critical section higher up the call chain.

For example, Average.Value() in the example is making the assumption that sum and count have been appropriately updated in lockstep. But if the lock is reentrant, this may not be true. Average is small enough that it’s trivial to check if this is a problem (ie. that Value is not called from Add while sum/count mismatch); more complex code is not, especially when it encounters future maintainers.

-eli

On Nov 2, 2022, at 7:43 AM, Robert Engels <reng...@ix.netcom.com> wrote:

I am curious though for an example that shows how a reentrant lock could violate this?

On Nov 2, 2022, at 2:38 AM, peterGo <go.peter...@gmail.com> wrote:


Guanyun,

I tried to think of a simple example.

type Average struct {
    sum   float64
    count int64
    mx    sync.Mutex
}

https://go.dev/play/p/4SLCLuqG246

1. An invariant represents a condition that does not change while the process progresses - Niklaus Wirth.

2. The additional invariant--Average = sum / count--is specific to the data structure that the mutex mx guards.

3. The shared variables sum and count are part of an invariant.

4. The Add method temporarily violates the invariant by updating sum but restores the invariant by updating count.

Peter

On Wednesday, November 2, 2022 at 12:49:41 AM UTC-4 name....@gmail.com wrote:
Hello,

This is a passage in book <The Go Programming Language>:
--------------------------------------------------------------------------------------------------------
There is a good reason Go’s mutexes are not re-entrant.

The purpose of a mutex is to ensure that certain invariants of the shared variables are
maintained at critical points during program execution.

One of the invariants is "no goroutine is accessing the shared variables", but there may be additional invariants specific to the data structures that the mutex guards.

When a goroutine acquires a mutex lock, it may assume that the invariants hold. While it holds the lock, it may update the shared variables so that the invariants are temporarily violated.

However, when it releases the lock, it must guarantee that order has been restored
and the invariants hold once again.

Although a re-entrant mutex would ensure that no other goroutines are accessing the shared variables, it cannot protect the additional invariants of those variables.
 --------------------------------------------------------------------------------------------------------

This passage is difficult for me to understand:
1. How to understand invariants "invariants"?
2. What kind of scenarios does “additional invariants” refer to?
3. What is the relationship between "shared variables" and "invariants"?
4. What does "...guarantee that order has been restored..." mean?

Thanks,
Guanyun

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/c2b53c11-4552-4b9a-a528-fc179ba0f513n%40googlegroups.com.

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/6F217FB7-077E-4CBE-B46E-4ADB7D7461A3%40ix.netcom.com.

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/9875F919-83A9-43E4-88EC-81D6C447ED9A%40siliconsprawl.com.

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/C7DDECB5-207B-4B01-937D-D86BD6BD6AD0%40ix.netcom.com.

--
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 on the web visit https://groups.google.com/d/msgid/golang-nuts/A14270D5-880D-4639-B6D8-6237F9C6ABF2%40siliconsprawl.com.

Reply via email to