C#中lock关键字主要是为确保当一个线程使用某些资源时,同时无法其他线程无法使用该资源。下面我们看看下面的小例子。

 static void Main(string[] args)
{
var c = new Counter();
var t1 = new Thread(() => TestCounter(c));
var t2 = new Thread(() => TestCounter(c));
var t3 = new Thread(() => TestCounter(c));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c.Count}");
Console.WriteLine("----------------------"); var c1 = new CounterWithLock();
t1 = new Thread(() => TestCounter(c1));
t2 = new Thread(() => TestCounter(c1));
t3 = new Thread(() => TestCounter(c1));
t1.Start();
t2.Start();
t3.Start();
t1.Join();
t2.Join();
t3.Join();
Console.WriteLine($"Total count:{c1.Count}"); }
  static void TestCounter(CounterBase c)
{
for (int i = ; i < ; i++)
{
c.Increment();
c.Decrement();
}
}
public abstract class CounterBase
{
public abstract void Increment(); public abstract void Decrement();
}
    public class Counter:CounterBase
{
public int Count { get; private set; }
public override void Increment()
{
Count++;
}
public override void Decrement()
{
Count--;
} }
    public class CounterWithLock : CounterBase
{
private readonly object _syncRoot = new object();
public int Count { get; private set; }
public override void Increment()
{
lock (_syncRoot)
{
Count++;
}
}
public override void Decrement()
{
lock (_syncRoot)
{
Count--;
}
}
}

  下面是输出结果,可以看到输出结果并非我们所期望的0,当然结果可能为0,但大多数情况下都不是。

  在这个例子中,当主程序启动时,创建了一个Counter对象。该类定义了一个可以递增和递减的简单计数器。然后我们启动了三个线程。这三个线程共享一个counter实例,在一个周期中进行一次递增和递减。这将导致不确定的结果。如果多次运行程序,则会打印出多种不同的计数器值。

  这是因为Counter类并不是线程安全的。当多个线程同时访问Counter对象时,第一个线程得到的Counter值10并增加为11。然后第二个进程得到的值是11并增加到12.第一个线程得到的Counter值12递减为11并保存在Counter中,同时第二个线程也执行了相同的操作。结果我们进行了两次递增操作但是有效的递减只有一次,这显然不对。这种情形被称为竞争条件(race condition)。竞争条件是多线程环境中非常常见的错误原因。

  为了确保不会发生以上情形,必须保证当有线程操作counter对象时,所有其他线程必须等待知道当前线程完成操作。我们可以使用lock关键词来实现这种行为。如果锁定了一个对象,需要访问该对象的所有线程都会处于阻塞状态,并等待直到该对象解除锁定。当然这有可能导致严重的性能问题,针对这一问题,我们后面再讲。

最新文章

  1. socket了解(转)
  2. 显式Intent和隐式Intent
  3. Openstack的keystone的user-role-list命令的使用
  4. Lucene.Net 站内搜索
  5. 使用 Java 开发兼容 IPv6 的网络应用程序
  6. hdu 5396 Expression(区间dp)
  7. linux运维基础__争取十月前研究的差不多
  8. Oracle 12C 简介
  9. ThinkPHP系统变量,常量,序列化,反序列化,缓存
  10. java1环境与简介
  11. CentOS下使用tcpdump网络抓包
  12. 项目(九) 企业级Memcached服务应用实践
  13. python爬虫学习之使用BeautifulSoup库爬取开奖网站信息-模块化
  14. python 输出颜色与样式的方法
  15. folly无锁队列,尝试添加新的函数
  16. Opatching PSU in Oracle Database 11g Release 2 RAC on RHEL6
  17. Quartz 2.3.0 升级感受
  18. Unix/Linux系统编程
  19. 单选按钮选中指定value值
  20. Linux内核之vmlinux与vmlinuz

热门文章

  1. 【Hibernate那点事儿】—— Hibernate应该了解的知识
  2. 查询python的安装路径
  3. March 3 2017 Week 9 Friday
  4. IOS 多媒体 使用总结
  5. 课堂笔记——while循环
  6. 转载:C/C++ typedef用法
  7. ORA-01950:对表空间 &#39;USERS&#39; 无权限
  8. JavaScript:改变 HTML 样式
  9. Extjs treePanel 的treestore重复加载问题解决
  10. 【SQL】Oracle的交集、并集、差集