c#锁定数组与数组索引
根据下面的代码c#锁定数组与数组索引,c#,multithreading,locking,C#,Multithreading,Locking,根据下面的代码 var array = new object[10]; for(int x = 0;x<array.Length;x++) array[x] = new object(); //Lock on Array lock(array){ //Do Stuff } //Lock on object of array lock(array[1]){ //Do Stuff } //lock on another object var o = array[
var array = new object[10];
for(int x = 0;x<array.Length;x++)
array[x] = new object();
//Lock on Array
lock(array){
//Do Stuff
}
//Lock on object of array
lock(array[1]){
//Do Stuff
}
//lock on another object
var o = array[1];
lock(o){
//Do Stuff
}
var数组=新对象[10];
对于(int x=0;x我从来都不喜欢使用lock
,因为多线程的复杂性
Scenrio 2和Scenrio 3是等价的。这些lock语句相互干扰(这是通过查看代码可以预期的)
场景1不影响2或3
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
public static object o;
public static object[] array;
static void Main(string[] args)
{
array = new object[10];
for (int x = 0; x < array.Length; x++)
array[x] = new object();
o = array[1];
var tasks = new Task[100];
Task t;
//t = Task.Run(() => lockArray(5000));
t = Task.Run(() => lockArrayIndex(5000));
//t = Task.Run(() => lockObject(5000));
for (int i = 0; i < tasks.Length; i++)
{
//tasks[i] = Task.Run(() => lockArray(1000));
//tasks[i] = Task.Run(() => lockArrayIndex(1000));
tasks[i] = Task.Run(() => lockObject(1000));
}
Task.WaitAll(tasks);
"done".Dump();
Console.ReadKey();
}
private static void lockArray(int input)
{
//Lock on Array
lock (array)
{
System.Threading.Thread.Sleep(input);
"Array".Dump();
}
}
private static void lockArrayIndex(int input)
{
//Lock on object of array
lock (array[1])
{
System.Threading.Thread.Sleep(input);
"Array[1]".Dump();
}
}
private static void lockObject(int input)
{
//lock on another object
lock (o)
{
System.Threading.Thread.Sleep(input);
"o".Dump();
}
}
}
public static class extenstions
{
public static void Dump(this string input)
{
Console.WriteLine(input);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间控制台应用程序1
{
班级计划
{
公共静态对象o;
公共静态对象[]数组;
静态void Main(字符串[]参数)
{
数组=新对象[10];
for(int x=0;xlockArray(5000));
t=Task.Run(()=>lockarayindex(5000));
//t=Task.Run(()=>lockObject(5000));
for(int i=0;ilockArray(1000));
//tasks[i]=Task.Run(()=>lockarayindex(1000));
tasks[i]=Task.Run(()=>lockObject(1000));
}
Task.WaitAll(任务);
“完成”。转储();
Console.ReadKey();
}
专用静态void锁数组(int输入)
{
//锁定阵列
锁(数组)
{
系统。线程。线程。睡眠(输入);
“Array.Dump();
}
}
私有静态void lockarayindex(int输入)
{
//锁定数组的对象
锁(数组[1])
{
系统。线程。线程。睡眠(输入);
“数组[1]”。Dump();
}
}
私有静态void锁对象(int输入)
{
//锁定另一个对象
锁(o)
{
系统。线程。线程。睡眠(输入);
“o”。Dump();
}
}
}
公共静态类扩展
{
公共静态无效转储(此字符串输入)
{
控制台写入线(输入);
}
}
}
进行第二次锁定,然后分别尝试第一次和第三次锁定,看看哪些被阻止,哪些可以被捕获。然后你就会知道哪个被锁定。我认为这不值得给出完整的答案,所以这里是一个注释:第二次和第三次锁定都锁定在同一个对象上:数组索引1处的对象。按照Servy的建议执行。在索引1的数组中有一个对象。在第三个示例中,您创建了一个引用同一对象的附加变量,但仍然只有一个对象同时包含o
和数组[1]
正在引用。您决不能,决不能编写这样的代码。这会造成错误的印象,认为数组现在处于一种神奇的状态,使其线程安全。实际上不会发生这种情况。始终声明一个专用变量来存储锁状态。几个优点之一是您不必问这个问题。另一个优点是ntage(re@HansPassant的评论)是,当你创建一个私有变量,如私有对象_myLock=new object();
,你的类外的任何人都不能弄乱你用作锁的对象。始终为你的锁指定一个私有(非值类型)对象-这样更安全、更清晰,“我从来都不喜欢……多线程的复杂性。”是的,很难做到正确,但是你的多线程代码应该(A)比同等的单线程程序更容易阅读,或者(B)比同等的单线程程序更快,或者(C)如果你不能达到其中一个目标,那么线程可能不是解决问题的正确方法。