저는 LINQ로 놀고 있었고 C# Monadic 구문을 이용하여 잠금을 작성하는 다음 아이디어를 생각해 냈습니다. 그것은 너무 단순 해 보였습니다. 그래서 StackOverflow에 게시하고 누군가가이 접근법으로 어떤 주요 문제점을 신속하게 발견 할 수 있는지 알아 보았습니다.LINQ를 사용하는 조합 가능 잠금. 누구든지이 문제를 볼 수 있습니까?
원자 적 구현 내에서 잠금을 주석 처리하면 계정이 손상된 것을 볼 수 있습니다.
이 아이디어는 명시 적 잠금없이 계정에서 작업을 작성할 수 있다는 것입니다.
using System;
using System.Collections.Generic;
using System.Linq;
namespace AtomicLinq
{
public static class AccountCombinators
{
public static IAtomic <Unit> TransferAndReverse(this Account accA,
Account accB,
double amount)
{
return from a in accA.TransferTo(accB, amount)
from b in accB.TransferTo(accA, amount)
select new Unit();
}
public static IAtomic<Unit> TransferTo(this Account accA,
Account accB,
double amount)
{
return from a in accA.Withdraw(amount)
from b in accB.Deposit(amount)
select new Unit();
}
public static IAtomic<double> Withdraw(this Account acc, double amount)
{
return Atomic.Create(() => acc.Amount -= amount);
}
public static IAtomic<double> Deposit(this Account acc, double amount)
{
return Atomic.Create(() => acc.Amount += amount);
}
}
static class Program
{
static void Main(string[] args)
{
var accA = new Account("John") { Amount = 100.0 };
var accB = new Account("Mark") { Amount = 200.0 };
var syncObject = new object();
Enumerable.Range(1, 100000).AsParallel().Select(_ => accA.TransferAndReverse(accB, 100).Execute(syncObject)).Run();
Console.WriteLine("{0} {1}", accA, accA.Amount);
Console.WriteLine("{0} {1}", accB, accB.Amount);
Console.ReadLine();
}
}
public class Account
{
public double Amount { get; set; }
private readonly string _name;
public Account(string name)
{
_name = name;
}
public override string ToString()
{
return _name;
}
}
#region Atomic Implementation
public interface IAtomic<T>
{
T Execute(object sync);
}
public static class Atomic
{
public static IAtomic<T> Create<T>(Func<object, T> f)
{
return new AnonymousAtomic<T>(f);
}
public static IAtomic<T> Create<T>(Func<T> f)
{
return Create(_ => f());
}
public static IAtomic<T> Aggregate<T>(this IEnumerable<IAtomic<T>> xs)
{
return xs.Aggregate((x, y) => from a in x
from b in y
select b);
}
public static IAtomic<K> SelectMany<T, V, K>(this IAtomic<T> m, Func<T, IAtomic<V>> f, Func<T, V, K> p)
{
return Create(sync =>
{
var t = m.Execute(sync);
var x = f(t);
return p(t, x.Execute(sync));
});
}
}
public class AnonymousAtomic<T> : IAtomic<T>
{
private readonly Func<object, T> _func;
public AnonymousAtomic(Func<object, T> func)
{
_func = func;
}
public T Execute(object sync)
{
lock (sync) // Try to comment this lock you'll see that the accounts get corrupted
return _func(sync);
}
}
#endregion Atomic Implementation
}
당신은 codereview.stackexchange 난 그냥 한 – flesh
에 게시 시도 할 수 있습니다. 감사합니다 – Holoed