
HANDLE hMutex = CreateMutex(...); ... DWORD WINAPI WaitForSingleObject(hMutant , IFINITE);
Mutex mutex = new Mutex(); ... mutex.WaitOne();
EventWaitHandle
AutoResetEvent
ManualResetEvent
Semaphore
Mutex
public abstract class WaitHandle : MarshalByRefObject, IDisposable {
public virtual void Close();
public void Dispose();
public virtual Boolean WaitOne();
public virtual Boolean WaitOne(Int32 millisecondsTimeout);
public static Int32 WaitAny(WaitHandle[] waitHandles);
public static Int32 WaitAny(WaitHandle[] waitHandles, Int32 millisecondsTimeout);
public static Boolean WaitAll(WaitHandle[] waitHandles);
public static Boolean WaitAll(WaitHandle[] waitHandles, Int32 millisecondsTimeout);
public static Boolean SignalAndWait(WaitHandle toSignal, WaitHandle toWaitOn);
public static Boolean SignalAndWait(WaitHandle toSignal, WaitHandle toWaitOn,
Int32 millisecondsTimeout, Boolean exitContext)
public SafeWaitHandle SafeWaitHandle { get; set; }
// Returned from WaitAny if a timeout occurs
public const Int32 WaitTimeout = 0x102;
}
public sealed class SimpleWaitLock : IDisposable {
private Semaphore m_AvailableResources;
public SimpleWaitLock(Int32 maximumConcurrentThreads) {
m_AvailableResources =
new Semaphore(maximumConcurrentThreads, maximumConcurrentThreads);
}
public void Enter() {
// Wait efficiently in the kernel for resource access, then return
m_AvailableResources.WaitOne();
}
public void Leave() {
// This thread doesn’t need access anymore; another thread can have it
m_ AvailableResources.Release();
}
public void Dispose() { m_AvailableResources.Close(); }
}
public class BlockingQueueWithAutoResetEvents <T>
{
private Queue <T> m_queue = new Queue <T>();
private Mutex m_mutex = new Mutex ();
private AutoResetEvent m_event = new AutoResetEvent (false );
public void Enqueue(T obj)
{
// Enter the critical region and insert into our queue.
m_mutex.WaitOne();
try
{
m_queue.Enqueue(obj);
}
finally
{
m_mutex.ReleaseMutex();
}
// Note that an item is available, possibly waking a consumer.
m_event.Set();
}
public T Dequeue()
{
// Dequeue the item from within our critical region.
T value;
bool taken = true ;
m_mutex.WaitOne();
try
{
// If the queue is empty, we will need to exit the
// critical region and wait for the event to be set.
while (m_queue.Count == 0)
{
taken = false ;
WaitHandle .SignalAndWait(m_mutex, m_event);
m_mutex.WaitOne();
taken = true ;
}
value = m_queue.Dequeue();
}
finally
{
if (taken)
{
m_mutex.ReleaseMutex();
}
}
return value;
}
}
public class BlockingBoundedQueue<T>
{
private Queue <T> m_queue = new Queue <T>();
private Mutex m_mutex = new Mutex ();
private Semaphore m_producerSemaphore;
private Semaphore m_consumerSemaphore;
public BlockingBoundedQueue(int capacity)
{
m_producerSemaphore = new Semaphore (capacity, capacity);
m_consumerSemaphore = new Semaphore (0, capacity);
}
public void Enqueue(T obj)
{
// Ensure the buffer hasn't become full yet. If it has, we will
// be blocked until a consumer takes an item.
m_producerSemaphore.WaitOne();
// Now enter the critical region and insert into our queue.
m_mutex.WaitOne();
try
{
m_queue.Enqueue(obj);
}
finally
{
m_mutex.ReleaseMutex();
}
// Note that an item is available, possibly waking a consumer.
m_consumerSemaphore.Release();
}
public T Dequeue()
{
// This call will block if the queue is empty.
m_consumerSemaphore.WaitOne();
// Dequeue the item from within our critical region.
T value;
m_mutex.WaitOne();
try
{
value = m_queue.Dequeue();
}
finally
{
m_mutex.ReleaseMutex();
}
// Note that we took an item, possibly waking producers.
m_producerSemaphore.Release();
return value;
}
}
多线程之旅
4.多线程之旅之四——浅谈内存模型和用户态同步机制
5.多线程之旅之五——线程池与I/O完成端口
6.多线程之旅六——异步编程模式,自己实现IAsyncResult
7.多线程之旅七——再谈内存模型
8.多线程之旅八——多线程下的数据结构
9.多线程之旅九——最后再回头总结一下
public class MyClass<T> : IMyList<T>
{
bool isReversed = false;
LinkedList<T> list = new LinkedList<T>();
Dictionary<T, List<T>> dic = new Dictionary<T, List<T>>();
public void AddFirst(T item)
{
if (!isReversed)
{
list.AddFirst(item);
}
else
{
list.AddLast(item);
}
CacheItemInDic(item);
}
private void CacheItemInDic(T item)
{
List<T> sameValueItems;
if (!dic.TryGetValue(item,out sameValueItems))
{
sameValueItems = new List<T>();
}
sameValueItems.Add(item);
}
public void AddLast(T item)
{
if (!isReversed)
{
list.AddLast(item);
}
else
{
list.AddFirst(item);
}
CacheItemInDic(item);
}
public void Remove(T item)
{
T cachedItem;
List<T> sameValueItems;
if (!dic.TryGetValue(item, out sameValueItems))
{
return;
}
else
{
cachedItem = sameValueItems[0];
list.Remove(item);
}
public void Reverse()
{
isReversed = !isReversed; ;
}
public IEnumerator<T> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

public class MyClass<T> : IMyList<T>
{
bool isReversed = false;
LinkedList<T> list = new LinkedList<T>();
Dictionary<T, List<LinkedListNode<T>>> dic = new Dictionary<T, List<LinkedListNode<T>>>();
public void AddFirst(T item)
{
LinkedListNode<T> node;
if (!isReversed)
{
node = list.AddFirst(item);
}
else
{
node = list.AddLast(item);
}
CacheItemInDic(item,node);
}
private void CacheItemInDic(T item,LinkedListNode<T> node)
{
List<LinkedListNode<T>> sameValueNodes;
if (!dic.TryGetValue(item,out sameValueNodes))
{
sameValueNodes = new List<LinkedListNode<T>>();
}
sameValueNodes.Add(node);
}
public void AddLast(T item)
{
LinkedListNode<T> node;
if (!isReversed)
{
node = list.AddLast(item);
}
else
{
node = list.AddFirst(item);
}
CacheItemInDic(item, node);
}
public void Remove(T item)
{
LinkedListNode<T> cachedNode;
List<LinkedListNode<T> > sameValueNodes;
if (!dic.TryGetValue(item, out sameValueNodes))
{
return;
}
else
{
cachedNode = sameValueNodes[0];
}
if (cachedNode == null) return;
list.Remove(cachedNode);
}
public void Reverse()
{
isReversed = !isReversed; ;
}
public IEnumerator<T> GetEnumerator()
{
LinkedListNode<T> node;
if (!isReversed)
node = list.First;
else
node = list.Last;
while (true)
{
if (node == null)
yield break;
yield return node.Value;
if (!isReversed)
node = node.Next;
else
node = node.Previous;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
static void Main()
{
MyClass<int> collection = new MyClass<int>();
for (int i = 1; i < 11; i++)
{
if(i%2 ==0)
collection.AddFirst(i);
else
collection.AddLast(i);
}
foreach (var i in collection)
{
Console.WriteLine(i);
}
collection.Reverse();
foreach (var i in collection)
{
Console.WriteLine(i);
}
}
一年的时间里写了一些东西,做个目录方便自己查找。也包含了自己打算写的一些东西。
一.网络协议
4.TCP和流
7.用TCP/IP实现自己简单的应用程序协议:其余部分(包括完整代码)
8.用TCP/IP实现自己简单的应用程序协议:最后再返回来看HTTP协议
二.多线程之旅
4.多线程之旅之四——浅谈内存模型和用户态同步机制
5.多线程之旅之五——线程池与I/O完成端口
6.多线程之旅六——异步编程模式,自己实现IAsyncResult
7.多线程之旅七——再谈内存模型
8.多线程之旅八——多线程下的数据结构
9.多线程之旅九——最后再回头总结一下
三.数据库漫谈
2.SQL SERVER中的聚集索引和非聚集索引
3.SQL SERVER对索引的利用分析
4.和SQL SERVER优化器斗智斗勇,如何写出更好的SQL语句
5.多个中间查询结果集中的各种类型连接
四、数据结构与算法
五、静态编译语言与动态语言的比较
1.可以转移到方法名,字符串,xml中。
2.并没有使编程变得更简单,只是把一部分变得更抽象,显得更强壮了而已。
3.IOC容器管理了对象的依赖关系,因此要在程序运行前启动。因为没有具体依赖的程序什么都不是。
1.观察者模式主要是为了解耦,注意并不是立刻通知。
2.在MVC的教科书定义中,Model采用的是观察者模式,也就是Model是被观察者,View是观察者,Model有任何改变的情况下,View都会接受到通知。
换句话说,只有当我们需要生成一个页面作为响应返回给客户端的时候,创建一个View并使用Model有意义。
因此其他时候Model的改变对于View来说都是没有意义的,也就没必要通知View
所以View就不再直接观察Model,而是通过Controller来作为中间人。因此Controller是一次Request就调用一次。
把引用对象作为参数传进一个方法,实际上是在栈上新分配了一块内存保存传入的地址。

如图所示,把局部变量name传入M2方法后,栈上新开了一块内存S,用来保存"joe"的地址。
其实拿string来说明不太合适,因为string类是不可变的。但是为借用CLR VIA C#中现成的图咱们就将就一下了。
这时如果能够直接修改s所指向的内容的话(在C#中string是不可变类,无法演示),外部的局部变量name由于和形参s指向的是同一个对象,因此name也会改变。(图1)
但是如果把s指向一个新的的string时,比如:
void M2(string s){
s = "new string";
}
那么这时再对s改变,name的内容不会改变。因为两个变量分别指向了堆上的不同string (图2)
用图来说明就是:

如果用上ref,在这种情况下,编译器将不会为形参s在栈上新分配一块内存,编译器将使用由调用者所指定的那个引用地址,按上图来说是使用name的地址。

在C中,为了解决这种栈上的变量复制问题,我们可以采用指向指针的指针,如 char[]** s 。
这时再对s修改,指向一个新的对象,外部的name也会改变。

由于用string的话,无法演示直接修改的情况,因为改变string实际上也是生成了新的string。因此我随便弄了个student类来演示。
代码示例如下:
class Student
{
public string name = "a";
}
class Program
{
static void Main(string[] args)
{
var s1 = new Student();
var s2 = new Student();
var s3 = new Student();
ModifyWithRef(ref s1);
ModifyWithoutRef(s2);
DirectlyModifyWithoutRef(s3);
Console.WriteLine("Directly modify without ref: "+s3.name); //结果被直接修改为c,对应图1
Console.WriteLine("without ref: "+s2.name); //结果仍为a,对应图2
Console.WriteLine("with ref: "+s1.name); //结果为c
Console.ReadLine();
}
static void ModifyWithRef(ref Student s)
{
s = new Student();
s.name = "c";
}
static void ModifyWithoutRef(Student s)
{
s = new Student();
s.name = "c";
}
static void DirectlyModifyWithoutRef(Student s)
{
s.name = "c";
}
}
你理解了吗?
