using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Test
{
class Program
{
static void Main()
{
var obj1 = new object();
var obj2 = new object();
Parallel.For(0, 10, (i) =>
{
var random = new Random(i);
for (int j = 0; j < 10; j++)
{
Thread.Sleep(random.Next(0, 100));
MultiLock.Lock((isSuccess) =>
{
Thread.Sleep(random.Next(0, 100));
Console.WriteLine(isSuccess.ToString());
}, TimeSpan.FromMilliseconds(random.Next(0, 100)), obj1, obj2);
}
});
}
}
public class MultiLock
{
public static void Lock(Action<bool> callback, TimeSpan timeout, params object[] lockObjects)
{
var sw = Stopwatch.StartNew();
for (;;)
{
int count = 0;
for (; count < lockObjects.Length; count++)
{
if (!Monitor.TryEnter(lockObjects[count], 0))
{
for (int i = 0; i < count; i++)
{
Monitor.Exit(lockObjects[i]);
}
break;
}
}
if (count == lockObjects.Length)
{
callback?.Invoke(true);
for (int i = 0; i < lockObjects.Length; i++)
{
Monitor.Exit(lockObjects[i]);
}
return;
}
if (sw.Elapsed > timeout)
{
break;
}
Thread.Sleep(100);
}
callback?.Invoke(false);
return;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkRpYWdub3N0aWNzOwp1c2luZyBTeXN0ZW0uTGlucTsKdXNpbmcgU3lzdGVtLlRleHQ7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmc7CnVzaW5nIFN5c3RlbS5UaHJlYWRpbmcuVGFza3M7CgpuYW1lc3BhY2UgVGVzdAp7CiAgICBjbGFzcyBQcm9ncmFtCiAgICB7CiAgICAgICAgc3RhdGljIHZvaWQgTWFpbigpCiAgICAgICAgewogICAgICAgICAgICB2YXIgb2JqMSA9IG5ldyBvYmplY3QoKTsKICAgICAgICAgICAgdmFyIG9iajIgPSBuZXcgb2JqZWN0KCk7CgogICAgICAgICAgICBQYXJhbGxlbC5Gb3IoMCwgMTAsIChpKSA9PgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICB2YXIgcmFuZG9tID0gbmV3IFJhbmRvbShpKTsKCiAgICAgICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IDEwOyBqKyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgVGhyZWFkLlNsZWVwKHJhbmRvbS5OZXh0KDAsIDEwMCkpOwogICAgICAgICAgICAgICAgICAgIE11bHRpTG9jay5Mb2NrKChpc1N1Y2Nlc3MpID0+CiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBUaHJlYWQuU2xlZXAocmFuZG9tLk5leHQoMCwgMTAwKSk7CiAgICAgICAgICAgICAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKGlzU3VjY2Vzcy5Ub1N0cmluZygpKTsKICAgICAgICAgICAgICAgICAgICB9LCBUaW1lU3Bhbi5Gcm9tTWlsbGlzZWNvbmRzKHJhbmRvbS5OZXh0KDAsIDEwMCkpLCBvYmoxLCBvYmoyKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSk7CiAgICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBjbGFzcyBNdWx0aUxvY2sKICAgIHsKICAgICAgICBwdWJsaWMgc3RhdGljIHZvaWQgTG9jayhBY3Rpb248Ym9vbD4gY2FsbGJhY2ssIFRpbWVTcGFuIHRpbWVvdXQsIHBhcmFtcyBvYmplY3RbXSBsb2NrT2JqZWN0cykKICAgICAgICB7CiAgICAgICAgICAgIHZhciBzdyA9IFN0b3B3YXRjaC5TdGFydE5ldygpOwoKICAgICAgICAgICAgZm9yICg7OykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaW50IGNvdW50ID0gMDsKCiAgICAgICAgICAgICAgICBmb3IgKDsgY291bnQgPCBsb2NrT2JqZWN0cy5MZW5ndGg7IGNvdW50KyspCiAgICAgICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAgICAgaWYgKCFNb25pdG9yLlRyeUVudGVyKGxvY2tPYmplY3RzW2NvdW50XSwgMCkpCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IGNvdW50OyBpKyspCiAgICAgICAgICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1vbml0b3IuRXhpdChsb2NrT2JqZWN0c1tpXSk7CiAgICAgICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBpZiAoY291bnQgPT0gbG9ja09iamVjdHMuTGVuZ3RoKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrPy5JbnZva2UodHJ1ZSk7CgogICAgICAgICAgICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbG9ja09iamVjdHMuTGVuZ3RoOyBpKyspCiAgICAgICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgICAgICBNb25pdG9yLkV4aXQobG9ja09iamVjdHNbaV0pOwogICAgICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGlmIChzdy5FbGFwc2VkID4gdGltZW91dCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBUaHJlYWQuU2xlZXAoMTAwKTsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY2FsbGJhY2s/Lkludm9rZShmYWxzZSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9Cn0K