I'm in a situation where I have a ASP.NET Web API 2 project hosted on IIS and I'm anticipating concurrency issues. I need to generate random numbers and make sure that they are unique (later stored in the database). To do so, I have implemented a simple in-memory RNG that rely on a static ConcurrentBag. I am aware that this implementation would imply risks on a distributed architecture. Rapidly, the code looks like this :
public interface IRandomNumberGenerator
{
string ReserveNumber();
string ReleaseNumber(string number);
}
public class InMemoryRandomNumberGenerator : IRandomNumberGenerator
{
private static readonly ConcurrentBag<string> Bag = new ConcurrentBag<string>();
public string ReserveNumber()
{
// Add
throw new NotImplementedException();
}
public string ReleaseNumber(string number)
{
// Remove
throw new NotImplementedException();
}
}
This code is intended to be used like so :
var number = rng.ReserveNumber();
StoreIntoDatabase(number);
rng.ReleaseNumber(number);
Am I using the ConcurrentBag collection appropriately?
Also note that I have simplified my example and that I am not interested in moving code into SQL and use SQL transaction to accomplish this task.
I guess you trying to solve a concurrency problem where many users click a button to generate a number. While ConcurrentBag might be OK to use from the concurrency perspective I see other problems:
"Bags are useful for storing objects when ordering doesn't matter, and unlike sets, bags support duplicates. " msdn. I think you were trying to avoid duplicates.
You need to have some sort of a protected section or a transaction for this sequence, otherwise concurrency issue may appear
var number = rng.ReserveNumber();
StoreIntoDatabase(number);
rng.ReleaseNumber(number);
I hope you don't roll out your own RNG, but reuse something like RNGCryptoServiceProvider.
I have revised the design. I switched to ConcurrentDictionary to avoid duplicates as pointed out by #oleksii. I use a byte because I don't use the value and there is no ConcurrentHashset to my knowledge.
NUnit test :
[Test]
public void GenerateStrings()
{
var gen1 = new ConcurrentStringGenerator("0123456789", 9);
for (int i = 0; i < 100; i++)
{
var str = gen1.Reserve();
Console.WriteLine(int.Parse(str).ToString("000-000-000"));
Assert.True(gen1.Release(str));
}
var gen2 = new ConcurrentStringGenerator("ABCDEFGHJKLMNPQRSTUVWXYZ", 3);
for (int i = 0; i < 100; i++)
{
var str = gen2.Reserve();
Console.WriteLine(str);
Assert.True(gen2.Release(str));
}
}
Implementation :
public class ConcurrentStringGenerator
{
private readonly Random _random;
private readonly string _charset;
private readonly int _length;
private readonly ConcurrentDictionary<string, byte> _numbers;
public ConcurrentStringGenerator(string charset, int length)
{
_charset = charset;
_length = length;
_random = new Random();
_numbers = new ConcurrentDictionary<string, byte>();
}
public string Reserve()
{
var str = Generate();
while (!_numbers.TryAdd(str, 0))
{
str = Generate();
}
return str;
}
public bool Release(string str)
{
byte b;
return _numbers.TryRemove(str, out b);
}
private string Generate()
{
return new string(Enumerable.Repeat(_charset, _length).Select(s => s[_random.Next(s.Length)]).ToArray());
}
}
#oleksii as for the protected section, I'm trying to avoid a lock statement over the sequence and use a concurrent collection instead. Can you be more specific on the following statement?
You need to have some sort of a protected section or a transaction for
this sequence, otherwise concurrency issue may appear
Related
I have a class with just one variable
public class C
{
int i;
}
And in another project file I create an array of classes
C[] classes = new C[100000];
So what i need to do to set some random value to the "i" variable in each class?
First you need to make C.i accessible. One way is to make C.i a public property. While you’re at it, public fields should be pascal cased and all identifiers should have meaningful names.
When naming public members of types, such as fields, properties, events, methods, and local functions, use pascal casing.
public class Foo {
public int Bar { get; set; }
}
Then you'd use System.Random. Instantiate it once and call Random.Next each time you want a random number.
using System;
var rand = new Random();
// int anyPositiveInt = rand.Next();
// int positiveIntLessThanFifteen = rand.Next(15);
// int intFromOneToFour = rand.Next(1, 5);
Finally, following the example in Creating N objects and adding them to a list, use System.Linq's Enumerable.Range, Enumerable.Select, and Enumerable.ToArray as follows:
Foo[] classes = Enumerable
.Range(0, 100000)
.Select(_ => new Foo { Bar = rand.Next() })
.ToArray();
If the requirement is to use a private field then I recant the earlier advice to make it a public property - properties might not have been taught yet
static void Main()
{
var r = new Random();
var maxValueOfI = 100;
var minValueOfI = -20;
var csArr = new C[100000];
for (var julius = 0; julius < csArr.Length; julius++) {
var brutus = r.Next(minValueOfI, maxValueOfI+1);
csArr[julius] = new C(brutus);
}
}
public class C
{
private int _i;
public C(int i){
_i = i;
}
}
So, what's going on here?
The main addition is a constructor to C. A constructor is a special method that is called by C# when a new object is constructed. Every class has one even if you can't see it (the compiler provides one if you don't). Constructors are methods that are intended to ensure the class is fully set up and ready to use. Because it's inside the class it has full access to all the data fields of the class:
public C(int i){
_i = i;
}
This constructor takes an int, and sets the private field _i to the value of the passed in number. It's quite common to use this naming pattern for fields (prefix with underscore) and it helps avoid a name collision with the arguments to the method (in this case called i). If they had both been called i the class one would have to be prefixed with this. and it's (IMHO) more clutter
This line of code calls the constructor:
csArr[julius] = new C(brutus);
We've previously calculated a random number between -30 and 100 (inclusive both ends) and stashed it in a variable called brutus. This number is passed to the constructor, which is called when we say new C. The resulting fully constructed C instance is stored in one of the array slots
try this
static void Main()
{
Random rand = new Random();
var max=100000;
C[] array = new C[max];
for (var i=0; i <max; i++)
array[i] = new C { Num = rand.Next(0, max)};
// or using a constructor
array[i] = new C (rand.Next(0, max));
}
public class C
{
public int Num {get; set;}
public C (int num)
{
Num=num;
}
public C (){}
}
First of all, in your current code i is a private field. Let's add a constructor to set this field:
public class C {
int i;
public C(int value) {
i = value;
}
}
Then you can try using Linq:
using System.Linq;
...
Random rand = new Random();
...
C[] classes = Enumerable
.Range(0, 100000)
.Select(i => new C(rand.Next(0, 100))) //TODO: Put the right range here
.ToArray();
Why I'm doing this:
So I'm trying to make an application for a game called clash royale, after winning the games there you get a "random" chest, which is actually not random... When you create your account you get a digit assigned to you from 0 to 239, and after that it follows a pattern for the chest drops. The applciation I'm making would take a user's entries and compare it to the pattern, thus being able to predict how soon the next chests of a higher quality would drop.
The help I need with the code:
Is it possible to make an array kind of... loop within itself.. So for example when going through the array in a loop, if "i" is 239, then adding +1 would take it back to the beginning, or #0 (239 not necessarily being the limit).
The class (and it's container that I want to loop):
class Chest
{
public int ID { get; set; }
public string Type { get; set; }
public Chest()
{
}
public Chest(int id, string type)
{
ID = id;
Type = type;
}
}
class ChestContainer
{
private Chest[] ChestList = new Chest[240];
public int Count { get; set; }
public ChestContainer(int size)
{
ChestList = new Chest[size];
}
public void Add(Chest chest)
{
ChestList[Count++] = chest;
}
public Chest Get(int index)
{
return ChestList[index];
}
}
Also wouldn't mind any tips to improve my class / container class, at the moment this is what I've been doing for pretty much my entire "career" as this is what we were thought in uni (minus the string override for the class).
You could use Modulo % in order to get a loop kind of thing.
If you replace the Container.Add method with the one below, the index will be "reset" (for lack of better words).
public void Add(Chest chest)
{
ChestList[Count++%(ChestList.Length)] = chest;
}
After updating the method, if you want an example, you can try the code below:
var container = new ChestContainer(240);
for (int i = 0; i < 1000; i++)
container.Add(new Chest(i, $"{i}"));
Edit In order to have the Get method working as well, modifying it as mentioned below will ensure your container works as expected:
public Chest Get(int index)
{
return ChestList[index%(ChestList.Length)];
}
To test it out, you can use the code below:
var container = new ChestContainer(240);
for (int i = 0; i < 1000; i++)
{
container.Add(new Chest(i, $"{i}"));
var value = container.Get(i);
}
You can overload the [] operator to define it's behaviour.
Something like this:
public static Chest operator [] (int index) {
return ChestList[index%240];
}
public Chest Get(int index)
{
return ChestList[index%240]; //put your limit here
}
How it works: % is the modulo operator.
It returns the remainder of a devision.
Example:
5/2 = 2, remaining 1
=> 5%2 = 1
In your case, when numbers higher than 239 are entered, with modulo it just wraps around.
I am interfacing with a back-end system, where I must never ever have more than one open connection to a given object (identified by it's numeric ID), but different consumers may be opening and closing them independently of one another.
Roughly, I have a factory class fragment like this:
private Dictionary<ulong, IFoo> _openItems = new Dictionary<ulong, IFoo>();
private object _locker = new object();
public IFoo Open(ulong id)
{
lock (_locker)
{
if (!_openItems.ContainsKey(id))
{
_openItems[id] = _nativeResource.Open(id);
}
_openItems[id].RefCount++;
return _openItems[id];
}
}
public void Close(ulong id)
{
lock (_locker)
{
if (_openItems.ContainsKey(id))
{
_openItems[id].RefCount--;
if (_openItems[id].RefCount == 0)
{
_nativeResource.Close(id);
_openItems.Remove(id);
}
}
}
}
Now, here is the problem. In my case, _nativeResource.Open is very slow. The locking in here is rather naive and can be very slow when there are a lot of different concurrent .Open calls, even though they are (most likely) referring to different ids and don't overlap, especially if they are not in the _openItems cache.
How do I structure the locking so that I am only preventing concurrent access to a specific ID and not to all callers?
What you may want to look into is a striped locking strategy. The idea is that you share N locks for M items (possible ID's in your case), and choose a lock such that for any ID the lock chosen is always the same one. The classic way of choosing locks for this technique is modulo division- simply divide M by N, take the remainder, and use the lock with that index:
// Assuming the allLocks class member is defined as follows:
private static AutoResetEvent[] allLocks = new AutoResetEvent[10];
// And initialized thus (in a static constructor):
for (int i = 0; i < 10; i++) {
allLocks[i] = new AutoResetEvent(true);
}
// Your method becomes
var lockIndex = id % allLocks.Length;
var lockToUse = allLocks[lockIndex];
// Wait for the lock to become free
lockToUse.WaitOne();
try {
// At this point we have taken the lock
// Do the work
} finally {
lockToUse.Set();
}
If you are on .net 4, you could try the ConcurrentDictionary with something along these lines:
private ConcurrentDictionary<ulong, IFoo> openItems = new ConcurrentDictionary<ulong, IFoo>();
private object locker = new object();
public IFoo Open(ulong id)
{
var foo = this.openItems.GetOrAdd(id, x => nativeResource.Open(x));
lock (this.locker)
{
foo.RefCount++;
}
return foo;
}
public void Close(ulong id)
{
IFoo foo = null;
if (this.openItems.TryGetValue(id, out foo))
{
lock (this.locker)
{
foo.RefCount--;
if (foo.RefCount == 0)
{
if (this.openItems.TryRemove(id, out foo))
{
this.nativeResource.Close(id);
}
}
}
}
}
If anyone can see any glaring issues with that, please let me know!
In my web application i am having following common objectList for all online users.
public static List<MyClass> myObjectList = new List<MyClass>();
so when multiple online users try to read data from this object myObjectList then are there any chances of thread synchronization issue.
In another scenario multiple users are reading from myObjectList and few of them are writing also but every user is writing on a different index of List . Every user may add a new item to this list . So now I think there are chances of synchronization issue.
How to write thread safe utility class that can read and write data from this object in safer way.
Suggestions are highly welcome
Code suggested by Angelo looks like this
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace ObjectPoolExample
{
public class ObjectPool<T>
{
private ConcurrentBag<T> _objects;
private Func<T> _objectGenerator;
public ObjectPool(Func<T> objectGenerator)
{
if (objectGenerator == null) throw new ArgumentNullException("objectGenerator");
_objects = new ConcurrentBag<T>();
_objectGenerator = objectGenerator;
}
public T GetObject()
{
T item;
if (_objects.TryTake(out item)) return item;
return _objectGenerator();
}
public void PutObject(T item)
{
_objects.Add(item);
}
}
class Program
{
static void Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
// Create an opportunity for the user to cancel.
Task.Factory.StartNew(() =>
{
if (Console.ReadKey().KeyChar == 'c' || Console.ReadKey().KeyChar == 'C')
cts.Cancel();
});
ObjectPool<MyClass> pool = new ObjectPool<MyClass> (() => new MyClass());
// Create a high demand for MyClass objects.
Parallel.For(0, 1000000, (i, loopState) =>
{
MyClass mc = pool.GetObject();
Console.CursorLeft = 0;
// This is the bottleneck in our application. All threads in this loop
// must serialize their access to the static Console class.
Console.WriteLine("{0:####.####}", mc.GetValue(i));
pool.PutObject(mc);
if (cts.Token.IsCancellationRequested)
loopState.Stop();
});
Console.WriteLine("Press the Enter key to exit.");
Console.ReadLine();
}
}
// A toy class that requires some resources to create.
// You can experiment here to measure the performance of the
// object pool vs. ordinary instantiation.
class MyClass
{
public int[] Nums {get; set;}
public double GetValue(long i)
{
return Math.Sqrt(Nums[i]);
}
public MyClass()
{
Nums = new int[1000000];
Random rand = new Random();
for (int i = 0; i < Nums.Length; i++)
Nums[i] = rand.Next();
}
}
}
I think i can go with this approach.
If you are using .NET 4.0 you are better off changing to one of the thread-safe collections already supported by the runtime, like for example a ConcurrentBag.
The concurrent bag however does not support access by index if I recall correctly so you may need to resort to a ConcurrentDictionary if you need access to an object by a given key.
If .NET 4.0 is not an option you should read the following blog post:
Why are thread safe collections so hard?
I have some unusual I need to do. I am wondering if anyone can think of an easy
way to make the change that I need. What I have is a
public class Report
{
public string[] Text { get; set; }
public string[] Image { get; set; }
public string[] Explanation { get; set; }
}
The report class can have any number of Texts, Images and Explanations and the size of each array is always the consistent but maybe be different for each report instance.
What I need to do is to be able to sort the array elements in a random order. So for example I might have
Report.Text[0] = "text0";
Report.Text[1] = "text1";
Report.Text[2] = "text2";
Report.Image[0] = "img0";
Report.Image[1] = "img1";
Report.Image[2] = "img2";
Report.Explanation[0] = "exp0";
Report.Explanation[1] = "exp1";
Report.Explanation[2] = "exp2";
then after sorting
Report.Text[0] = "text2";
Report.Text[1] = "text0";
Report.Text[2] = "text1";
Report.Image[0] = "img2";
Report.Image[1] = "img0";
Report.Image[2] = "img1";
Report.Explanation[0] = "exp2";
Report.Explanation[1] = "exp0";
Report.Explanation[2] = "exp1";
Can anyone think of a simple way to do this? All I can think of is that I need to create a
new temporary object of the same size and do some kind of swapping. But I am not sure how
to randomize. The reason I am asking is just in case someone has had this need in the past.
I would strongly recommend that you refactor this to create a single class to encapsulate the { Text, Image, Explanation } tuple. At that point, the code will be cleaner and it'll be trivial to reorder the values. Heck, you may not even need a Report type at that point... you may just be able to have a List<ReportItem> or whatever. You'd only need a separate Report type if you wanted to add extra behaviour or data to tie things together.
(As an aside, I hope you don't really have public fields for these to start with...)
If you then have a question around shuffling a single collection, a modified Fisher-Yates shuffle is probably the easiest approach. You could do this with the multiple arrays as well, but it wouldn't be nice - and would have to be specific to Report... whereas you could easily write a generic Fisher-Yates implementation based on IList<T>. If you search on Stack Overflow, you should easily be able to find a few existing implementations :)
If you choose to change your class to the following:
public class Report
{
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
You could then do this using an extension method:
(See answer on this SO question)
Then call it this way:
List<Report> reports = new List<Report> { /* create list of reports */ }
Random rnd = new Random();
foreach (Report r in reports.Shuffle(rnd)) {
/* do something with each report */
}
Why don't you create a class
public class Report
{
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
and then create a List of those objects and manage it through the list properties:
IList<Report> yourList = new List<Report>()
Here is my solution
class StringWrapper
{
public int Index;
public string Str;
}
public string[] MixArray(string[] array)
{
Random random = new Random();
StringWrapper[] wrappedArray = WrapArray(array);
for (int i = 0; i < wrappedArray.Length; i++)
{
int randomIndex = random.Next(0, wrappedArray.Length - 1);
wrappedArray[i].Index = randomIndex;
}
Array.Sort(wrappedArray, (str1, str2) => str1.Index.CompareTo(str2.Index));
return wrappedArray.Select(wrappedStr => wrappedStr.Str).ToArray();
}
private StringWrapper[] WrapArray(string[] array)
{
int i = 0;
return array.Select(str => new StringWrapper {Index = ++i, Str = str}).ToArray();
}
Then you can call MixArray for each Report object for each property you wand to randomize.
I am not sure I am fond of this direction, but ...
To do exactly what you ask (the law, not the spirit of the law), you will have to add additional arrays and pull items over. In addition, for each array, you will need a List or similar to store the items you have already randomly pulled over. After that, things are simple. Use the Random class to create random numbers, check if the item has already been moved (using the List), if not store the result in the new array/list, add the value to your List to make sure you do not move the same item twice. Once everything is moved, set this new array to the old array.
Now, what is the business reason for randomizing? That might affect whether or not this is a good idea.
ADDED:
After examination of skeet's response, here is a way to solve this if you can use the following type of class:
public class Report {
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
Here is one "down and dirty" type of sort:
private static SortedList<int, Report> SortRandomly(List<Report> reports)
{
Random rnd = new Random((int)DateTime.Now.Ticks);
List<int> usedNumbers = new List<int>();
SortedList<int, Report> sortedReports = new SortedList<int, Report>();
int maxValue = reports.Count;
foreach(Report report in reports)
{
bool finished = false;
int randomNumber = 0;
//Get unique random (refactor out?)
while(!finished)
{
randomNumber = rnd.Next(0, maxValue);
if(!usedNumbers.Contains(randomNumber))
{
finished = true;
usedNumbers.Add(randomNumber);
}
}
sortedReports.Add(randomNumber, report);
}
return sortedReports;
}
Note, you can also work to keep the sort in order and randomly picking from the original list, which means you can, in theory, keep it as a list.
private static List<Report> SortRandomly(List<Report> reports)
{
Random rnd = new Random((int)DateTime.Now.Ticks);
List<Report> outputList = new List<Report>();
List<int> usedNumbers = new List<int>();
int maxValue = reports.Count-1;
while(outputList.Count < reports.Count)
{
int randomNumber = rnd.Next(0, maxValue);
if(!usedNumbers.Contains(randomNumber))
{
outputList.Add(reports[randomNumber]);
}
}
return outputList;
}
Even better, consider sorting the list of numbers first and then grabbing the reports, in an order manner. Once again, the above are down and dirty implementations and using the specific requirements will certainly refine the algorithms.