C#线程同步 lock关键字后的参数是不是随便用什么都行?

2024-12-29 15:01:28
推荐回答(2个)
回答1:

我觉得用 "令牌" 这个概念来解释"锁"比较容易理解

比如做一件事件.需要令牌才能开始. 定义一个对象,就是创建了一个令牌.只有拥有令牌的线程才能进行执行.
lock(对象) 就好比某个线程申请令牌并把令牌拿走了.
执行完 {....} 这里的内容后回把令牌还回去

这时候再看你新建的对象,也就是"令牌"了.这个令牌必须唯一.这样才能在一个线程执行的时候.其他线程申请不到令牌.

能成为令牌的必须是引用类型,(你可以简单理解为必须实实在在是个东西)
打个比方,如果知道你百度的账户密码,谁都能登录你账户了.这个可以理解为值类型的,不能成为令牌.
但是,网上银行就不同了.他必须要U盾才能转走钱.这个U盾就是唯一的.同一时间只能一个人在用.这个就可以成为令牌了.

以上解释只是放在一个初学的角度来帮助理解.有什么欠缺的地方大家可以一起探讨一下

回答2:

楼上的虽然写的多,但是我觉得不但没说清楚,反而把问题弄复杂了。
直接回答楼主这个问题可能你就明白了。

在同一个例子中同时用 比如lock(对象A),lock(一个变量),lock(全局变量),结果是一样的吗?
首先,要确保在你lock后要引用的任何“东西”是可以访问到的。
接下来,如果要让多线程同步,必须保证这个“东西”在多个线程同时启动时是一致的。
假设一个线程函数:
public void mutiThread()
{
int a;
lock(a)
{
//一些代码
}
}
这个锁就是没意义的,因为每个线程函数进来后都创建了自己的变量a,用不同的变量来锁不会实现同步。

那就是说,lock后的“东西”仅仅是一个标识,变量也好,对象也好,都不要紧,重要的是在这个“东西”上做一个标记,以决定接下来的代码是否可以被继续访问。
上面那个例子,每个函数都有自己的a,thread1中给自己的变量a标记后,thread2根本不知道这回事,它也只标记自己的变量a。如果换成一个全局变量(对象皆可),thread1进来后标记这个变量,thread2进来后,访问的是同一个变量(因为是全局的),它发现已经被标记,就不会往下执行,而是等待这个标记被清除后才继续。两个线程是这样,扩展到多个线程同理,这就实现了多线程同步。