在研究Table Hints的使用时,我遇到了这两个问题:
这两个问题的答案都说,在使用时(UPDLOCK, HOLDLOCK),其他进程将无法读取该表上的数据,但我没有看到这一点.为了测试,我创建了一个表并启动了两个SSMS窗口.从第一个窗口,我运行了一个使用各种表提示从表中选择的事务.当事务正在运行时,我从第二个窗口运行了各种语句,看看哪些会被阻止.
测试表:
CREATE TABLE [dbo].[Test](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Value] [nvarchar](50) NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
从SSMS窗口1:
BEGIN TRANSACTION
SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
从SSMS窗口2(运行以下之一):
SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = …Run Code Online (Sandbox Code Playgroud) 何时在C#中使用Monitor类或lock关键字来确保线程安全?
编辑:
到目前为止,答案似乎lock是对Monitor课程的一系列调用的简写.锁定电话到底是什么?或者更明确地说,
class LockVsMonitor
{
private readonly object LockObject = new object();
public void DoThreadSafeSomethingWithLock(Action action)
{
lock (LockObject)
{
action.Invoke();
}
}
public void DoThreadSafeSomethingWithMonitor(Action action)
{
// What goes here ?
}
}
Run Code Online (Sandbox Code Playgroud)
更新
谢谢大家的帮助:我发布了另一个问题,作为您提供的一些信息的后续跟进.由于您似乎精通这一领域,我发布了链接:此锁定和管理锁定异常的解决方案有什么问题?
我注意到在Windows上执行文件(.exe或.dll)时,它被锁定,无法删除,移动或修改.
另一方面,Linux不会锁定正在执行的文件,你可以删除,移动或修改它们.
当Linux没有时,为什么Windows会锁定?锁定有优势吗?
我需要在Android应用程序中禁用Home和其他系统按钮.
例如: MX Player(见谷歌播放) -你可以按"锁定"在播放器屏幕上的图标,并锁定所有的硬件和软件系统的按钮.
它工作正常,没有根本.
我在一些具有不同Android版本的设备上测试了它.我试图拆解Kids Lock(插件),但不知道它是如何工作的.
我需要像Kids Lock(插件)这样的解决方案MX Player: - 禁用Home,Back和所有其他系统按钮.
有什么建议?
在C#中访问bool字段原子?特别是,我需要锁定:
class Foo
{
private bool _bar;
//... in some function on any thread (or many threads)
_bar = true;
//... same for a read
if (_bar) { ... }
}
Run Code Online (Sandbox Code Playgroud) 在ac#threading应用程序中,如果我要锁定一个对象,让我们说一个队列,如果发生异常,该对象是否会保持锁定状态?这是伪代码:
int ii;
lock(MyQueue)
{
MyClass LclClass = (MyClass)MyQueue.Dequeue();
try
{
ii = int.parse(LclClass.SomeString);
}
catch
{
MessageBox.Show("Error parsing string");
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,catch之后的代码没有执行 - 但我一直想知道锁是否会被释放.
我们遇到了一个代码块的问题,这个代码块在数据库缓慢的情况下响应很差(它在查询超时时瘫痪).我们已经创建了一个补丁,并且正在通过回归运行它.
我们不能超时.我已经从SQL Mgmt Studio打开了一个事务并更新了每一行来锁定它们,但这并不会导致INSERT超时(这就是我需要的).
我可以通过T-SQL轻松获得表级锁吗?或者我必须在主人身边摆弄?或者我可以轻松强制超时而不锁定?任何输入都表示赞赏.
我正在使用此代码对ReaderWriterLock进行非常愚蠢的基准测试,其中读取的次数比写入次数多4倍:
class Program
{
static void Main()
{
ISynchro[] test = { new Locked(), new RWLocked() };
Stopwatch sw = new Stopwatch();
foreach ( var isynchro in test )
{
sw.Reset();
sw.Start();
Thread w1 = new Thread( new ParameterizedThreadStart( WriteThread ) );
w1.Start( isynchro );
Thread w2 = new Thread( new ParameterizedThreadStart( WriteThread ) );
w2.Start( isynchro );
Thread r1 = new Thread( new ParameterizedThreadStart( ReadThread ) );
r1.Start( isynchro );
Thread r2 = new Thread( new ParameterizedThreadStart( ReadThread ) …Run Code Online (Sandbox Code Playgroud) 我从一个函数开始一个新的任务,但我不希望它在同一个线程上运行.我不关心它运行在哪个线程上,只要它是一个不同的线程(因此这个问题中给出的信息没有帮助).
我保证TestLock在允许Task t再次输入之前,以下代码将始终退出吗?如果没有,建议的设计模式是什么来防止再次出现?
object TestLock = new object();
public void Test(bool stop = false) {
Task t;
lock (this.TestLock) {
if (stop) return;
t = Task.Factory.StartNew(() => { this.Test(stop: true); });
}
t.Wait();
}
Run Code Online (Sandbox Code Playgroud)
编辑:基于Jon Skeet和Stephen Toub的以下答案,确定性地防止重入的一种简单方法是传递CancellationToken,如此扩展方法所示:
public static Task StartNewOnDifferentThread(this TaskFactory taskFactory, Action action)
{
return taskFactory.StartNew(action: action, cancellationToken: new CancellationToken());
}
Run Code Online (Sandbox Code Playgroud)