提供对共享资源的锁定
providing locks on shared resources
所以我正在尝试使用共享资源来解决线程问题。
c#corner (link 1) 和 msdn (link 2) 上的示例提供了基本语法示例和一些理论框架,因此我理解为进程锁定共享资源的基本前提。现在,我的问题是:
在同一代码块中访问和操作多个共享资源时(在"pseudocode"下面的一个循环爬虫进程从共享堆栈中弹出一个URL,评估当前url 到已检查 URL 的共享列表,然后将下载的数据推送到另一个共享堆栈),我是否需要将属于特定共享资源的每个代码段包含在 lock 语句中?
看起来是这样,因为 c# 中的 "lock (this) {}" 结构在后台实现了 "Monitor" (link 3),并且 Monitor.Enter 和 Monitor.Exit 都只接受单个对象作为参数。
老实说,我还没有把它编码出来并进行测试。但是我在阅读时以及之后在布置代码结构时(下面的 "pseudocode")都在想这个问题。如果我的假设是正确的,我将锁定结构的起点和终点大写,我怀疑它们所在的位置。
谁能clarify/validate给我这个?
(因为我还没有获得必要的声誉分数,所以我 post 像这样编辑了 links,你可以在底部找到它们;@mods:如果我这样做违反了任何规定,让我知道,我会修改 post。)
program starts;
stack (urlsToCheck) is created (static, String);
list (checkedUrls) is created (static, String);
stack (unparsedHTML) is created (static, Tuple(string, Byte[]);
user provides seed url;
seed url is pushed to top op stack (urlsTocheck);
thread is created for Crawler method GetData();
<!--research possibilities for multiple threads in relation to stack sizes-->
<!--in case of multiple threads : threadpool + object (crawler) array?-->
thread is started:
Crawler 1 is created;
Crawler 1 starts method GetData:
loop:
<!--//check loop for lock/unlock locations//-->
Crawler 1 evaluates size of stack (unparsedHTML):
if(size > 100):
wait 1000 ms;
Crawler 1 evaluates size of stack (unparsedHTML);
else:
continue;
LOCK;
Crawler 1 evaluates size of stack (urlsToCheck):
if(size > 0):
Crawler 1 pops url from stack (urlsToCheck);
continue;
else:
wait 1000 ms;
Crawler 1 evaluates size of stack (urlsToCheck);
Crawler 1 evaluates url for membership in List (checkedUrls):
if(membership):
discard url;
pop url from stack (urlsToCheck);
evaluate url for membership in List (checkedUrls);
else:
continue;
UNLOCK;
LOCK;
Crawler 1 downloads data from url;
Crawler makes tuple of url and data;
Crawler pushes tuple onto stack (unparsedHTML);
UNLOCK;
end loop;
1) http:// www.c-sharpcorner.com/UploadFile/mgold/MultithreadingIntro10062005000439AM/MultithreadingIntro.aspx
2) https:// msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
3) https:// msdn.microsoft.com/en-us/library/hf5de04k%28v=vs.110%29.aspx
我的意见是,是的,您希望将属于特定共享资源的每个段封装在一个单独的锁中(类似于上面的锁)。一个主要原因是这有助于最大限度地减少任何给定线程占用资源的时间。我还发现它有助于防止线程持有锁但试图获取另一个锁的情况,这会迅速挂起您的程序。这仅仅是因为您的锁定部分通常较短并且更容易在您的代码中发现此问题。这不是万无一失,但有帮助。
显然,释放和获取锁都涉及成本,因此时间或资源敏感的环境需要在频繁释放和获取锁的成本与等待锁的成本之间找到适当的平衡。在您的示例中,这意味着如果您在整个代码块周围只持有一个锁,程序 运行 会更快,或者如果您坚持当前的释放和获取方案,程序会 运行 更快移动到新的共享资源时有新锁吗?根据我的经验,后者更好。
我所说的有各种各样的注意事项和例外情况,您在实际实现代码时可能会发现自己的一些注意事项和例外情况,但您目前对如何加锁的想法与我想的一样继续。
所以我正在尝试使用共享资源来解决线程问题。 c#corner (link 1) 和 msdn (link 2) 上的示例提供了基本语法示例和一些理论框架,因此我理解为进程锁定共享资源的基本前提。现在,我的问题是:
在同一代码块中访问和操作多个共享资源时(在"pseudocode"下面的一个循环爬虫进程从共享堆栈中弹出一个URL,评估当前url 到已检查 URL 的共享列表,然后将下载的数据推送到另一个共享堆栈),我是否需要将属于特定共享资源的每个代码段包含在 lock 语句中?
看起来是这样,因为 c# 中的 "lock (this) {}" 结构在后台实现了 "Monitor" (link 3),并且 Monitor.Enter 和 Monitor.Exit 都只接受单个对象作为参数。
老实说,我还没有把它编码出来并进行测试。但是我在阅读时以及之后在布置代码结构时(下面的 "pseudocode")都在想这个问题。如果我的假设是正确的,我将锁定结构的起点和终点大写,我怀疑它们所在的位置。
谁能clarify/validate给我这个?
(因为我还没有获得必要的声誉分数,所以我 post 像这样编辑了 links,你可以在底部找到它们;@mods:如果我这样做违反了任何规定,让我知道,我会修改 post。)
program starts;
stack (urlsToCheck) is created (static, String);
list (checkedUrls) is created (static, String);
stack (unparsedHTML) is created (static, Tuple(string, Byte[]);
user provides seed url;
seed url is pushed to top op stack (urlsTocheck);
thread is created for Crawler method GetData();
<!--research possibilities for multiple threads in relation to stack sizes-->
<!--in case of multiple threads : threadpool + object (crawler) array?-->
thread is started:
Crawler 1 is created;
Crawler 1 starts method GetData:
loop:
<!--//check loop for lock/unlock locations//-->
Crawler 1 evaluates size of stack (unparsedHTML):
if(size > 100):
wait 1000 ms;
Crawler 1 evaluates size of stack (unparsedHTML);
else:
continue;
LOCK;
Crawler 1 evaluates size of stack (urlsToCheck):
if(size > 0):
Crawler 1 pops url from stack (urlsToCheck);
continue;
else:
wait 1000 ms;
Crawler 1 evaluates size of stack (urlsToCheck);
Crawler 1 evaluates url for membership in List (checkedUrls):
if(membership):
discard url;
pop url from stack (urlsToCheck);
evaluate url for membership in List (checkedUrls);
else:
continue;
UNLOCK;
LOCK;
Crawler 1 downloads data from url;
Crawler makes tuple of url and data;
Crawler pushes tuple onto stack (unparsedHTML);
UNLOCK;
end loop;
1) http:// www.c-sharpcorner.com/UploadFile/mgold/MultithreadingIntro10062005000439AM/MultithreadingIntro.aspx
2) https:// msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
3) https:// msdn.microsoft.com/en-us/library/hf5de04k%28v=vs.110%29.aspx
我的意见是,是的,您希望将属于特定共享资源的每个段封装在一个单独的锁中(类似于上面的锁)。一个主要原因是这有助于最大限度地减少任何给定线程占用资源的时间。我还发现它有助于防止线程持有锁但试图获取另一个锁的情况,这会迅速挂起您的程序。这仅仅是因为您的锁定部分通常较短并且更容易在您的代码中发现此问题。这不是万无一失,但有帮助。
显然,释放和获取锁都涉及成本,因此时间或资源敏感的环境需要在频繁释放和获取锁的成本与等待锁的成本之间找到适当的平衡。在您的示例中,这意味着如果您在整个代码块周围只持有一个锁,程序 运行 会更快,或者如果您坚持当前的释放和获取方案,程序会 运行 更快移动到新的共享资源时有新锁吗?根据我的经验,后者更好。
我所说的有各种各样的注意事项和例外情况,您在实际实现代码时可能会发现自己的一些注意事项和例外情况,但您目前对如何加锁的想法与我想的一样继续。