在另一个线程调用readMVar
之后,我的代码似乎挂在putMVar
上。我不希望发生这种情况,但这就是我所观察到的。我的主线程创建了两个新线程,每个线程都可以访问共享的MVar
m。
线程1:
do
putStrLn "tick"
x <- readMVar m
putStrLn "tock"
线程2:
do
putMVar m 0
putStrLn "put m0"
void $ tryTakeMVar m
putStrLn "take m"
putMVar m 1
putStrLn "put m1"
主要:
do
m <- newEmptyMVar
<start thread 1>
<start thread 2>
在以下情况下,我的程序挂起:
两个线程可以访问共享的MVar m
,该MVar最初为空。 readMVar m
上的线程1块。同时,线程2调用putMVar m ...
。此时,线程1 可以继续进行,但让我们假设它没有。然后,线程2调用tryTakeMVar m
,大概清空了整个MVar
。然后线程2再次调用putMVar m ...
。这种情况对应于以下输出:
tick
put m0
take m
put m1
<hang>
这是怎么回事?我希望应该打印“ tock”,因为线程2充满了MVar,但是我的程序只是挂起了。
答案 0 :(得分:5)
我在尝试调试空间泄漏时将MVar实现从 function addstudent()
{
var firstname = $("#firstname").val();
var lastname = $("#lastname").val();
var imageuploaded = $("#imageupload")[0].files[0];
var rememberme = $("#rememberme").is(":checked");
var newsletter = $("#newsletter").is(":checked");
var gender = $("input[name=gender]:checked").val();
var studentDetails = new FormData();
studentDetails.append("FirstName", firstname);
studentDetails.append("LastName", lastname);
studentDetails.append("ImageUploaded", imageuploaded);
studentDetails.append("RememberMe", rememberme);
studentDetails.append("IsSubscribed", newsletter);
studentDetails.append("Gender", gender);
$.ajax({
url: "/Student/InsertStudent",
type:"POST",
dataType: "json",
contentType: false,
processData: false,
data: studentDetails,
success: onsuccessinsert,
error:onerrorinsert
});
return false;
}
切换到<form class="form-horizontal" id="studentform" autocomplete="off">
<input type="hidden" id="hiddenid" />
<div class="form-group">
<label for="firstname" class="col-sm-2 control-label"> Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="firstname"
name="firstname" placeholder="Enter First Name"/>
</div>
</div>
<div class="form-group">
<label for="lastname" class="col-sm-2 control-label">Last
Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="lastname"
placeholder="Enter Last Name"/>
</div>
</div>
<div class="form-group">
<label for="imageinput" class="col-sm-2 control-label">Image
Upload</label>
<div class="col-sm-10">
<input type="file" class="form-control-file" id="imageupload"
placeholder="Please Select a Image"
accept="image/jpeg,image/jpg,image/gif,image/png,image/bmp" />
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" id="rememberme" value="true" >
Remember me</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" id="newsletter"> Subscribed To
Newsletter</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="radio">
<label><input type="radio" name="gender" value="male"
id="gender1" /> Male</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="radio">
<label><input type="radio" name="gender" value="female"
id="gender2" /> Female</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success"
onclick="addstudent()" id="insertbtn">Sign in</button>
</div>
</div>
。但是正如问题所表明的那样,我的代码使用了 public JsonResult InsertStudent(StudentDetails studentDetails)
{
try
{
string filename = Guid.NewGuid() +
studentDetails.ImageUploaded.FileName;
string imagefullpath = Server.MapPath(@"~\ImageUploaded\") +
filename;
string imageshortpath = @"WebApplication1\ImageUploaded\" +
filename;
studentDetails.ImageFullUrl = imagefullpath;
studentDetails.ImageShortUrl = imageshortpath;
studentDetails.ImageName = filename;
studentDetails.ImageUploaded.SaveAs(imagefullpath);
return
Json(dbcontextStudentDetails.insertstudent(studentDetails),
JsonRequestBehavior.AllowGet);
}
catch (Exception message)
{
return Json(message);
}
}
,由于某些原因,base
没有提供。因此,前阵子,我像这样实现strict-concurrency
:
tryReadMVar
没有真正考虑其含义。从那以后,我就忘记了所有要做的事情。正如Daniel所指出的,旧版本的strict-concurrency
曾经做过类似的事情,但是新版本具有原子的tryReadMVar
实现。因此,即使我使用的是新版本的GHC,由于使用了tryReadMVar :: (NFData a) => MVar a -> IO (Maybe a)
tryReadMVar m = do
mm <- tryTakeMVar m
case mm of
Nothing -> return ()
Just a -> putMVar m a
return mm
,该问题仍然被重新引入。
同时,死锁在以下情况下发生(丹尼尔描述):
base
tryReadMVar
中使用strict-concurrency
获取mvar。putMVar
tryTakeMVar
tryReadMVar
内尝试tryTakeMVar
时线程1死锁事实证明,拥有原子putMVar
很有用!