#Modify Loops while its looping?

33 messages · Page 1 of 1 (latest)

willow cobalt
#

Got a Question:

    for _, search := range Utils.Playlist {
        ..SomeCode
        Utils.Playlist = Utils.Playlist[1:]
    }

if Utils.Playlist is modified somewhere else in the Code while its Looping will it catch onto the added stuff or does it only use the Elements that are in there upon Start of the Loop. Sorry I am not a native English Speaker as you may see so if something is unclear let me know
Like does it only loop trought the elements that are in Utils.Playlist at the time the loop started or does it also loop trough elements that are getting added while it is already looping

#

Okey it does not take the newly added Elements into account

verbal anchor
#

Expression on the "right" side of the range is evaluated once at the beginning of the loop, so changing Utils.Playlist won't have any effect.

#

However, since you are in the same time changing Utils.Playlist and looping throw it, it is considered as data race, so the behavior is considered as undefined (you should not rely on previous mentioned evaluation).

#

But lets @graceful storm confirm this about data race, just to be sure

graceful storm
#

it is a data race to read and write, or write and write from multiple goroutines

#

unless the accesses are synchronized

verbal anchor
#

So, the program is "illegal"?

graceful storm
#

as described possibly

verbal anchor
#

@graceful storm It confused me that you wrote "from multiple goroutines" since here is only one goroutine

graceful storm
#

the multiple goroutines is important because "somewhere else in the Code" says very little

verbal anchor
graceful storm
#

it's not a data race

verbal anchor
#

@graceful storm Since it is just one goroutine, it will see the change, so it can't be considered as data race? So data race is only when we have multiple goroutines?

graceful storm
#

yes because the execution model of a goroutine is specified to be sequential

#

every line executes after the preceding line

verbal anchor
graceful storm
#

this is in terms of observable behaviour, the compiler is free to reorder things so long as that premise holds

#
a = 1
b = 2
println(a, b)```
can be compiled as ```go
a = 1
b = 2
println(a, b)``` or ```go
b = 2
a = 1
println(a, b)```
because the assignments are independent, so long the program prints `1, 2` it is a legal compilation
verbal anchor
#

@graceful storm And about synchronization (like mutex, channels etc) when we say that, it means that compiler/hardware/golang scheduler etc will make sure all participants (goroutines) in that synchronization end up seeing the same data at the end of sync? This can include things like disabling compilers optimizations, disabling usage of some local copy of "shared" variable etc.?

graceful storm
#

no because that would involve the compiler knowing when things are scheduled, which it can't
what the compiler guarantees for correctly written programs (that use synchronization primitives) is that all happens before relationships are honoured, not what exact values the operations see

go func() {
  for {
    lock()
    a = 1
    unlock()
  }
}

go func() {
  for {
    lock()
    a = 2
    unlock()
  }
}

go func() {
  for {
    lock()
    print(a)
    unlock()
  }
}```
this program has a infinite number of valid sequencings, the compiler guarantees that all writes that happened before taking the lock are visible after acquiring the lock, not the order in which they happen necessarily as that depends on schedulling
#

with respect to the memory model, this is a race free program, but its output is still non deterministic

verbal anchor
# graceful storm no because that would involve the compiler knowing when things are scheduled, wh...

Yes, I agree with that. We can't know how will it execute (in which order), but I want to say that synchronization is the process in which we are doing everything to ensure that the data is visible in the same way to all participant after synchronization. And the process of ensuring that (that everyone sees the shared data in the same way) can involve different things. So, in your example, the sync technique is lock()/unlock() and it can include various things that are implemented in the background to ensure it (for example, I am giving something random: between lock and unlock don't use local copy of variables (a) - which can be used for optimization purposes, don't optimize code between lock and unlock). I hope you get my point 😄 and you agree with it? I'm struggling a bit with the sync/threads etc

graceful storm
#

synchronization is the process in which we establish a partial or total order of operations in a program
in the example above, I use locks to establish a partial order between the 3 participants, in which I guarantee that print will see any value that was synchronized before it

yes, synchronization is inherently a limiter to the compiler - it limits the number of potential compilation results to the ones whose behaviour complies with some sequentially consistent interleaving of operations
the locks above place fences that ensure all code before them actually executes before them, meaning that for go b = 2 lock() a = 1 unlock() then go lock() a = 1 unlock() b = 2 would be an invalid ordering and therefore the compiler can't do it even if it considers it to be faster

the compiler is still free to optimize between lock and unlock, so long as it doesn't violate the relationships between the memory operations

#
lock()
a = 1
a = 2
a = 3
unlock()```
for instance, the above can (and is) optimized to ```go
lock()
a = 3
unlock()```
#

because the lock and unlock act as sequence points, and every assignment depends on the previous one, the latter is a valid compilation

#

any read that synchronizes after the unlock has to see what happened before the unlock, since all writes happened before the unlock, and all writes sequence after each other, a read cannot observe neither 1 nor 2

#

but to the general question "does synchronization inhibit what the compiler can do?" yes, that's the goal

verbal anchor
#

@graceful storm ...and what it all includes depends on the implementation of a particular synchronization technique

graceful storm
#

if by "at the end of the synchronization, everyone sees the data in the same way" you mean everyone that synchronizes after sees the side effects of what synchronized before that is correct