Skip to content

Conversation

@hctrdev
Copy link
Collaborator

@hctrdev hctrdev commented Feb 22, 2021

Description

Update the RandomStringGenerator class to use a static Random variable to ensure that when multiple instances of this class are created, they do not all use the same initial seed (based on system time). By using a static instance, the random generator is shared and will always use a single seed.

This issue has been observed on a project that uses this library, but was not reproduceable as a test in this project.

TODO

  • Update CHANGELOG

Hector added 2 commits February 22, 2021 19:31
Update the `RandomStringGenerator` class to use a static `Random` variable
to ensure that when multiple instances of this class are created, they do
not all use the same initial seed (based on system time). By using a static
instance, the random generator is shared and will always use a single seed.
This issue has been observed on a project that uses this library, but was
not reproduceable as a test in this project.
Update the CHANGELOG file to include a reference to the random string
generator fix.
@hctrdev hctrdev added the bug Something isn't working label Feb 22, 2021
@ColmBhandal
Copy link
Owner

ColmBhandal commented Feb 23, 2021

Fix looks good. The time seed will be per program instance rather than per object instance, and no term in the sequence will be shared by multiple objects. So you should get random behaviour across multiple program instances and object instances within a program. The only potential issue I can think of is multi-threading. What if two objects try to access the static random variable at the same time, and somehow both end up getting the same term in the sequence? My guess is that C# has that covered by only allowing one thread concurrent access to the object at a time. So I wouldn't worry about this. Just a thought.

Just a note on the issue. It must have only been happening when multiple random objects were created in such rapid succession that there was no measurable time difference between them. If there's any sort of pause, the random sequences will get a different seed:

https://dotnetfiddle.net/L8SSuJ

But if there's no pause, they'll probably get the same seed:

https://dotnetfiddle.net/TwlZmc

Explicitly seeding the date-time doesn't help:

(int) DateTime.Now.Ticks & 0x0000FFFF

https://dotnetfiddle.net/dB4Joy

So yeah, the best solution I can think of is the one you implemented.

ColmBhandal
ColmBhandal previously approved these changes Feb 23, 2021
Update how the code creats instances of the `Random` class to ensure that
the code is thread-safe. The new code uses a static global `Random`
instance that generates seeds for each thread-specific instance.
@hctrdev
Copy link
Collaborator Author

hctrdev commented Feb 23, 2021

Very good point on the thread-safety of this solution. I hadn't thought of that.

I did a bit of investigation and Random is NOT thread-safe. Based on this discussion: https://stackoverflow.com/questions/3049467/is-c-sharp-random-number-generator-thread-safe

I updated the PR with an updated implementation that is thread-safe. It works by creating a global static instance that is used to generate seeds for thread-specific instances of the Random class. Note that the thread-specific instances are still static, but they are static to their thread, not to the entire application.

@ColmBhandal
Copy link
Owner

Interesting. Clever use of a global random variable for locking & seeding.

@hctrdev hctrdev merged commit 5c15272 into develop Feb 23, 2021
@hctrdev hctrdev deleted the agile/fix/random-string-generator-producing-duplicates branch February 23, 2021 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants