1.一种资源一把锁,锁的资源粒度比较小,如行锁;
2.多个资源一把锁,锁的资源粒度比较大,如表锁;
3.锁是资源的持有规则,我持有,则其它人不能持有
4.等待句柄,对象协作信号方式,是一种通知方式,如同红绿灯一样。
5.能锁对象的,就不能lock类的静态对象。
6.能锁私有的,不能lock公共,公有有问题。
======================
锁:
等待句柄:
其他:
Parallel LINQ
Task Parallel Library(TPL)
Scheduler
ThreadPool
协同数据结构
Coordination
Data Structure
==========================
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
public static int amount = 100;
public static object syncObj = new object();
static void Main(string[] args)
{
for (int i = 0; i < 10; i++ )
{
Thread myThread = new Thread(new ThreadStart(test));
myThread.Start();
Thread myThread1 = new Thread(new ThreadStart(test1));
myThread1.Start();
}
}
static void test()
{
int rnd = new Random().Next(10, 100);
lock (SyncMember.CreateInstence("bsz"))
{
if (amount > rnd)
{
Thread.Sleep(new Random().Next(20, 100));
amount = amount - rnd;
}
}
Console.WriteLine(amount);
}
static void test1()
{
int rnd = new Random().Next(10, 100);
lock (SyncMember.CreateInstence("bsz1"))
{
if (amount > rnd)
{
Thread.Sleep(new Random().Next(20, 100));
amount = amount - rnd;
}
}
Console.WriteLine(amount);
}
}
public sealed class SyncMember
{
private static Dictionary<string, SyncMember> syncMemberDic = new Dictionary<string, SyncMember>();
private static object syncObject = new object();
private SyncMember() { }
public static SyncMember CreateInstence(string memberId)
{
if (!syncMemberDic.ContainsKey(memberId))
{
lock (syncObject)
{
if (!syncMemberDic.ContainsKey(memberId))
{
syncMemberDic.Add(memberId, new SyncMember());
}
}
}
return syncMemberDic[memberId];
}
}
}
=============================
如果是private static object syncObject = new object();则是所有会员中只能有一个会员进行操作
而使用syncMemberDic后是会员同一个时间点上只能进行一次操作:
例如:
lock (SyncMember.CreateInstence(memberId))
{
MemberInfo memberInfo = IMEMBER.GetInfo(memberId);
if (responseInfo.AgentAmount <= memberInfo.TotalAmount && memberInfo.TotalAmount > 0)
{
try
{
RESERVE_WS.Reserve(reserveId);//调用外部系统,时间长,所以有可能同时有两个线程进行
}
catch
{
throw new SoapException("外部系统出现未知错误", new XmlQualifiedName("err315"));
}
IRESERVE.UpdateConfirm(memberId, reserveId, saleAmount, agentAmount);
}
else
{
//建议将以下语句移动Validate()方法中,并采用Resource方式
throw new SoapException("WebServcie商户信用金额不够", new XmlQualifiedName("err502"));
}
}
总结:
需要同步的数据TotalAmount,同步有种方式,互斥防,回滚补
事后补,机率小些,事前防,则需要根据每个会员来进行lock
损失率的代价,如果合理的损失率代价小于防补代价,则可考虑不防补