1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
// C5 example: locking 2005-11-07
// Compile with
// csc /r:C5.dll Locking.cs
using System;
using System.Threading;
using C5;
using SCG = System.Collections.Generic;
namespace Locking {
class Locking {
static ArrayList<int> coll = new ArrayList<int>();
// static SCG.List<int> coll = new SCG.List<int>();
static readonly int count = 1000;
public static void Main(String[] args) {
Console.WriteLine("Adding and removing without locking:");
RunTwoThreads(delegate { AddAndRemove(15000); });
Console.WriteLine("coll has {0} items, should be 0", coll.Count);
coll = new ArrayList<int>();
Console.WriteLine("Adding and removing with locking:");
RunTwoThreads(delegate { SafeAddAndRemove(15000); });
Console.WriteLine("coll has {0} items, should be 0", coll.Count);
Console.WriteLine("Moving items without locking:");
ArrayList<int> from, to;
from = new ArrayList<int>();
to = new ArrayList<int>();
for (int i=0; i<count; i++)
from.Add(i);
RunTwoThreads(delegate { while (!from.IsEmpty) Move(from, to); });
Console.WriteLine("coll has {0} items, should be {1}", to.Count, count);
Console.WriteLine("Moving items with locking:");
from = new ArrayList<int>();
to = new ArrayList<int>();
for (int i=0; i<count; i++)
from.Add(i);
RunTwoThreads(delegate { while (!from.IsEmpty) SafeMove(from, to); });
Console.WriteLine("coll has {0} items, should be {1}", to.Count, count);
}
public static void RunTwoThreads(Act run) {
Thread t1 = new Thread(new ThreadStart(run)),
t2 = new Thread(new ThreadStart(run));
t1.Start(); t2.Start();
t1.Join(); t2.Join();
}
// Concurrently adding to and removing from an arraylist
public static void AddAndRemove(int count) {
for (int i=0; i<count; i++)
coll.Add(i);
for (int i=0; i<count; i++)
coll.Remove(i);
}
private static readonly Object sync = new Object();
public static void SafeAddAndRemove(int count) {
for (int i=0; i<count; i++)
lock (sync)
coll.Add(i);
for (int i=0; i<count; i++)
lock (sync)
coll.Remove(i);
}
public static void SafeAdd<T>(IExtensible<T> coll, T x) {
lock (sync) {
coll.Add(x);
}
}
public static void Move<T>(ICollection<T> from, ICollection<T> to) {
if (!from.IsEmpty) {
T x = from.Choose();
Thread.Sleep(0); // yield processor to other threads
from.Remove(x);
to.Add(x);
}
}
public static void SafeMove<T>(ICollection<T> from, ICollection<T> to) {
lock (sync)
if (!from.IsEmpty) {
T x = from.Choose();
Thread.Sleep(0); // yield processor to other threads
from.Remove(x);
to.Add(x);
}
}
}
}
|