www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mutexes and locking

reply "alexhairyman" <alexhairyman gmail.com> writes:
I think I'm missing something big, but I'm having troubles with 
mutexes (using in a parallel foreach loop somewhere else); Why do 
the trylocks return true shouldn't they return false because the 
mutex is already locked? I don't think this is a phobos bug, I'm 
on OSX using dmd 2.065

import core.sync.mutex;
import std.stdio;

void main()
{
   Mutex m = new Mutex;
   m.lock();
   writefln("%s", m.tryLock());
   writefln("%s", m.tryLock());
   return;
}

produces:
true
true

Thanks!
   Alex
Mar 02 2014
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/02/2014 10:38 PM, alexhairyman wrote:

 I think I'm missing something big, but I'm having troubles with mutexes
 (using in a parallel foreach loop somewhere else); Why do the trylocks
 return true shouldn't they return false because the mutex is already
 locked?
The documentation says that Mutex is a recursive lock, meaning that the holder of the lock can lock it even further. :) There is an internal reference count so that the lock must be unlocked the equal number of times that it has been locked.
 I don't think this is a phobos bug, I'm on OSX using dmd 2.065

 import core.sync.mutex;
 import std.stdio;

 void main()
 {
    Mutex m = new Mutex;
    m.lock();
    writefln("%s", m.tryLock());
    writefln("%s", m.tryLock());
The lock count is now 3. You must unlock it 3 times so that another thread can lock it.
    return;
 }

 produces:
 true
 true

 Thanks!
    Alex
Ali
Mar 02 2014
next sibling parent reply "alexhairyman" <alexhairyman gmail.com> writes:
On Monday, 3 March 2014 at 07:38:05 UTC, Ali Çehreli wrote:
 On 03/02/2014 10:38 PM, alexhairyman wrote:

 I think I'm missing something big, but I'm having troubles
with mutexes
 (using in a parallel foreach loop somewhere else); Why do the
trylocks
 return true shouldn't they return false because the mutex is
already
 locked?
The documentation says that Mutex is a recursive lock, meaning that the holder of the lock can lock it even further. :) There is an internal reference count so that the lock must be unlocked the equal number of times that it has been locked.
Oh okay, that makes sense.
 I don't think this is a phobos bug, I'm on OSX using dmd 2.065

 import core.sync.mutex;
 import std.stdio;

 void main()
 {
    Mutex m = new Mutex;
    m.lock();
    writefln("%s", m.tryLock());
    writefln("%s", m.tryLock());
The lock count is now 3. You must unlock it 3 times so that another thread can lock it.
    return;
 }

 produces:
 true
 true

 Thanks!
    Alex
Ali
Okay, so when doing something like this Mutex hashlock; void tdigest(string path) { MD5Digest thasher = new MD5Digest; thasher.put(read(path)); //read the path in to the MD5 API hashlock.lock(); hashkey[path] = thasher.finish(); hashlock.unlock(); } void main() { hashlock = new Mutex(); ... other stuff foreach(string s ; tp.parallel(array of strings)) { tdigest(s); } ... even more stuff } it will fail because the parallel foreach uses the main thread is being used which does some funky stuff? I'm trying to figure out how to implement this (for reference I'm just trying to create a big hash map of files and their md5's)
Mar 03 2014
next sibling parent "yazd" <yazan.dabain gmail.com> writes:
On Monday, 3 March 2014 at 08:18:04 UTC, alexhairyman wrote:
 On Monday, 3 March 2014 at 07:38:05 UTC, Ali Çehreli wrote:
 On 03/02/2014 10:38 PM, alexhairyman wrote:

 I think I'm missing something big, but I'm having troubles
with mutexes
 (using in a parallel foreach loop somewhere else); Why do the
trylocks
 return true shouldn't they return false because the mutex is
already
 locked?
The documentation says that Mutex is a recursive lock, meaning that the holder of the lock can lock it even further. :) There is an internal reference count so that the lock must be unlocked the equal number of times that it has been locked.
Oh okay, that makes sense.
 I don't think this is a phobos bug, I'm on OSX using dmd 
 2.065

 import core.sync.mutex;
 import std.stdio;

 void main()
 {
   Mutex m = new Mutex;
   m.lock();
   writefln("%s", m.tryLock());
   writefln("%s", m.tryLock());
The lock count is now 3. You must unlock it 3 times so that another thread can lock it.
   return;
 }

 produces:
 true
 true

 Thanks!
   Alex
Ali
Okay, so when doing something like this Mutex hashlock; void tdigest(string path) { MD5Digest thasher = new MD5Digest; thasher.put(read(path)); //read the path in to the MD5 API hashlock.lock(); hashkey[path] = thasher.finish(); hashlock.unlock(); } void main() { hashlock = new Mutex(); ... other stuff foreach(string s ; tp.parallel(array of strings)) { tdigest(s); } ... even more stuff } it will fail because the parallel foreach uses the main thread is being used which does some funky stuff? I'm trying to figure out how to implement this (for reference I'm just trying to create a big hash map of files and their md5's)
You have to remember that global scope variables are thread-local by default. So your hashlock mutex is actually only initialized in the main thread. Try adding __gshared before declaring hashlock and see if it works.
Mar 03 2014
prev sibling parent "Sean Kelly" <sean invisibleduck.org> writes:
For what it's worth, you can also do:

auto m = new Mutex;
sycnchronized (m) {
      // do stuff
}

The synchronized block will call lock on enter and unlock on
exit, even as a result of a throw.
Mar 04 2014
prev sibling parent reply "Jeremy DeHaan" <dehaan.jeremiah gmail.com> writes:
On Monday, 3 March 2014 at 07:38:05 UTC, Ali Çehreli wrote:
 The documentation says that Mutex is a recursive lock, meaning 
 that the holder of the lock can lock it even further. :) There 
 is an internal reference count so that the lock must be 
 unlocked the equal number of times that it has been locked.
Maybe this is because I haven't done much work with multi-threading, but this seems like a strange thing. What would be the benefits of locking a mutex more than once? It makes sense to me that a mutex should be allowed to be locked only once, and anything else trying to lock it get's held up until it has been unlocked, or a false is returned in the case of a tryLock. and this may seem like a silly question(like I said, not much multi-threading experience), but what determines the holder of a lock? Is it the thread or is it a specific function? Or something else?
Mar 05 2014
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/05/2014 09:49 AM, Jeremy DeHaan wrote:

 On Monday, 3 March 2014 at 07:38:05 UTC, Ali Çehreli wrote:
 The documentation says that Mutex is a recursive lock, meaning that
 the holder of the lock can lock it even further. :) There is an
 internal reference count so that the lock must be unlocked the equal
 number of times that it has been locked.
Maybe this is because I haven't done much work with multi-threading,
Same here. :) I have learned about this concept years ago at a company that I had joined recently. I wrote a function like the following: void foo() { lock(mutex); // ... code that needs to be protected by a lock ... unlock(mutex); } The problem was, foo() could be called from different contexts, some of which had already locked the same mutex. I was told that I could not do that because the lock was not recursive.
 It makes sense to me that a mutex should be
 allowed to be locked only once, and anything else trying to lock it
 get's held up until it has been unlocked,
This design does not differentiate the same thread as somebody else and allows what I had tried to do above. Of course, I could have checked whether the lock was owned by me and then lock otherwise, but doing that becomes unnecessary here.
 and this may seem like a silly question(like I said, not much
 multi-threading experience), but what determines the holder of a lock?
 Is it the thread or is it a specific function? Or something else?
I think it is the thread. Ali
Mar 05 2014
prev sibling parent "Kagamin" <spam here.lot> writes:
We use non-recursive locks too. The pattern is:
---
bool wasMyLock=obj.isMyLock();
if(!wasMyLock)obj.lock();
...code...
if(!wasMyLock)obj.unlock();
---
Mar 06 2014